Count of "a"s and "b"s must be equal. Did you get it computer?

76

10

In the popular (and essential) computer science book, An Introduction to Formal Languages and Automata by Peter Linz, the following formal language is frequently stated:

definition

mainly because this language can not be processed with finite-state automata. This expression mean "Language L consists all strings of 'a's followed by 'b's, in which the number of 'a's and 'b's are equal and non-zero".

Challenge

Write a working program/function which gets a string, containing "a"s and "b"s only, as input and returns/outputs a truth value, saying if this string is valid the formal language L.

  • Your program cannot use any external computation tools, including network, external programs, etc. Shells are an exception to this rule; Bash, e.g., can use command line utilities.

  • Your program must return/output the result in a "logical" way, for example: returning 10 instead of 0, "beep" sound, outputting to stdout etc. More info here.

  • Standard code golf rules apply.

This is a . Shortest code in bytes wins. Good luck!

Truthy test cases

"ab"
"aabb"
"aaabbb"
"aaaabbbb"
"aaaaabbbbb"
"aaaaaabbbbbb"

Falsy test cases

""
"a"
"b"
"aa"
"ba"
"bb"
"aaa"
"aab"
"aba"
"abb"
"baa"
"bab"
"bba"
"bbb"
"aaaa"
"aaab"
"aaba"
"abaa"
"abab"
"abba"
"abbb"
"baaa"
"baab"
"baba"
"babb"
"bbaa"
"bbab"
"bbba"
"bbbb"

Leaderboard

Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.

/* Configuration */

var QUESTION_ID = 85994; // Obtain this from the url
// It will be like https://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 48934; // This should be the user ID of the challenge author.

/* App */

var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page;

function answersUrl(index) {
  return "https://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

function commentUrl(index, answers) {
  return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;
}

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(answer_page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      answers_hash = [];
      answer_ids = [];
      data.items.forEach(function(a) {
        a.comments = [];
        var id = +a.share_link.match(/\d+/);
        answer_ids.push(id);
        answers_hash[id] = a;
      });
      if (!data.has_more) more_answers = false;
      comment_page = 1;
      getComments();
    }
  });
}

function getComments() {
  jQuery.ajax({
    url: commentUrl(comment_page++, answer_ids),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      data.items.forEach(function(c) {
        if (c.owner.user_id === OVERRIDE_USER)
          answers_hash[c.post_id].comments.push(c);
      });
      if (data.has_more) getComments();
      else if (more_answers) getAnswers();
      else process();
    }
  });  
}

getAnswers();

var SCORE_REG = /<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

var OVERRIDE_REG = /^Override\s*header:\s*/i;

function getAuthorName(a) {
  return a.owner.display_name;
}

function process() {
  var valid = [];
  
  answers.forEach(function(a) {
    var body = a.body;
    a.comments.forEach(function(c) {
      if(OVERRIDE_REG.test(c.body))
        body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
    });
    
    var match = body.match(SCORE_REG);
    if (match)
      valid.push({
        user: getAuthorName(a),
        size: +match[2],
        language: match[1],
        link: a.share_link,
      });
    
  });
  
  valid.sort(function (a, b) {
    var aB = a.size,
        bB = b.size;
    return aB - bB
  });

  var languages = {};
  var place = 1;
  var lastSize = null;
  var lastPlace = 1;
  valid.forEach(function (a) {
    if (a.size != lastSize)
      lastPlace = place;
    lastSize = a.size;
    ++place;
    
    var answer = jQuery("#answer-template").html();
    answer = answer.replace("{{PLACE}}", lastPlace + ".")
                   .replace("{{NAME}}", a.user)
                   .replace("{{LANGUAGE}}", a.language)
                   .replace("{{SIZE}}", a.size)
                   .replace("{{LINK}}", a.link);
    answer = jQuery(answer);
    jQuery("#answers").append(answer);

    var lang = a.language;
    if (/<a/.test(lang)) lang = jQuery(lang).text();
    
    languages[lang] = languages[lang] || {lang: a.language, user: a.user, size: a.size, link: a.link};
  });

  var langs = [];
  for (var lang in languages)
    if (languages.hasOwnProperty(lang))
      langs.push(languages[lang]);

  langs.sort(function (a, b) {
    if (a.lang > b.lang) return 1;
    if (a.lang < b.lang) return -1;
    return 0;
  });

  for (var i = 0; i < langs.length; ++i)
  {
    var language = jQuery("#language-template").html();
    var lang = langs[i];
    language = language.replace("{{LANGUAGE}}", lang.lang)
                       .replace("{{NAME}}", lang.user)
                       .replace("{{SIZE}}", lang.size)
                       .replace("{{LINK}}", lang.link);
    language = jQuery(language);
    jQuery("#languages").append(language);
  }

}
body { text-align: left !important}

#answer-list {
  padding: 10px;
  width: 290px;
  float: left;
}

#language-list {
  padding: 10px;
  width: 290px;
  float: left;
}

table thead {
  font-weight: bold;
}

table td {
  padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">
<div id="answer-list">
  <h2>Leaderboard</h2>
  <table class="answer-list">
    <thead>
      <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>
    </thead>
    <tbody id="answers">

    </tbody>
  </table>
</div>
<div id="language-list">
  <h2>Winners by Language</h2>
  <table class="language-list">
    <thead>
      <tr><td>Language</td><td>User</td><td>Score</td></tr>
    </thead>
    <tbody id="languages">

    </tbody>
  </table>
</div>
<table style="display: none">
  <tbody id="answer-template">
    <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>
<table style="display: none">
  <tbody id="language-template">
    <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>

user55673

Posted 2016-07-20T19:12:01.463

Reputation:

"Your program cannot use any external computation tools , including network , external programs etc" is already in our standard loopholes. – Leaky Nun – 2016-07-20T19:35:04.303

24Can the input be empty? (You're saying it's not part of the language, but not whether it's an input we need to consider.) – Martin Ender – 2016-07-20T20:04:01.697

1What if our language doesn't have truthy or falsy? Would empty string == truthy and non-empty string == falsy be acceptable? – James – 2016-07-20T20:20:26.190

@LeakyNun it never hurts to specify it explicitly anyways – John Dvorak – 2016-07-21T07:43:52.533

I recommend a falsey test case like "aababb". Also please clarify, are concatenations of valid strings valid? – LLlAMnYP – 2016-07-21T08:36:06.423

@LLIAMnYP No , they aren't . Only strings in format of ab where a is before b and their counts are equal and non-zero , as explained in main post . – None – 2016-07-21T08:38:21.753

Oh, I see now, I've overlooked an appropriate falsey test case. – LLlAMnYP – 2016-07-21T08:59:43.570

5Nice challenge, but I think the title could be a little less ambiguous (i.e. a mention of a^n b^n or similar, rather than just the number of as equalling the number of bs) – Sp3000 – 2016-07-21T12:28:28.867

1@Sp3000 I choosed this title because it looked fun . I may change it later to sth else ... – None – 2016-07-21T13:27:05.897

When you say "can not be processed with finite-state automata", you're not talking about finite state automata with loops, right? If you are, how do you explain that I did it in sed?

– someonewithpc – 2016-07-22T22:25:04.177

1I'm a little surprised that in 50+ answers I'm the only one to use a paser generator. To be sure it's not strictly competitive on length, but the problem posed is one of parsing a simple but non-trivial language. I'd very much like to see answers in other compiler-compiler syntaxes because I am not widely familiar with the choices. – dmckee --- ex-moderator kitten – 2016-07-22T22:47:41.583

1@someonewithpc this is what I found in Peter Linz's book . I also believe that it's not possible , because the automata must store n in some way . the main problem is that , the count of as and bs must be equal , otherwise it was possible . (note that for a finite possibilities of n it's possible to make a machine with many states that accepts this language, (like a^2k b^2k) but I haven't specified any limit for n . ) also I think your sed answer is actually a Turing machine , but I'm not sure about that. – None – 2016-07-25T10:06:21.167

Is it a given that the string will contain as and bs only? Or do we have to make sure we're not allowing cs and ds? – SQB – 2016-07-25T15:45:37.623

@SQB I'm not sure that I understood what you meant but input contains nothing other than as and bs . – None – 2016-07-25T17:26:00.677

@GLASSIC He wants to know if the parser needs to be prepared to reject an input like aaabbc (which I have assumed it must), or if it can assume that no c will appear in the input. – dmckee --- ex-moderator kitten – 2016-07-25T22:42:03.450

@dmckee indeed. One approach could be checking if the second half of the word is the first half of the word, +1 on each letter. (I'm entertaining the thought of a brainf*ck entry). – SQB – 2016-07-26T10:50:11.603

@dmckee The fact that the Python answer using translate is a valid one, indicates that my assumption is correct. Otherwise printab would be incorrectly deemed a correct input. – SQB – 2016-07-27T16:01:59.483

What about "rrss" or "rrzz"? It depends from the alphabetical letter too? – RosLuP – 2017-08-30T01:08:05.363

Answers

34

MATL, 5 4 bytes

tSP-

Prints a non-empty array of 1s if the string belongs to L, and an empty array or an array with 0s (both falsy) otherwise.

Thanks to @LuisMendo for golfing off 1 byte!

Try it online!

How it works

t      Push a copy of the implicitly read input.
 S     Sort the copy.
  P    Reverse the sorted copy.
   -   Take the difference of the code point of the corresponding characters
       of the sorted string and the original.

Dennis

Posted 2016-07-20T19:12:01.463

Reputation: 196 637

7My second (working) MATL answer. :) – Dennis – 2016-07-21T00:49:37.593

2Strange definition of truthy and falsy: 'aabb' gives -1 -1 1 1 is truthy. 'aaabb' gives -1 -1 0 1 1 and is falsy – Etoplay – 2016-07-25T08:02:42.800

3@Etoplay A non-empty array with all its values nonzero is truthy. It's the definition used in Matlab and Octave – Luis Mendo – 2016-07-25T12:36:42.803

147

Python 3, 32 bytes

eval(input().translate(")("*50))

Outputs via exit code: Error for false, no error for True.

The string is evaluated as Python code, replacing parens ( for a and ) for b. Only expressions of the form a^n b^n become well-formed expressions of parentheses like ((())), evaluating to the tuple ().

Any mismatched parens give an error, as will multiple groups like (()()), since there's no separator. The empty string also fails (it would succeed on exec).

The conversion ( -> a, ) -> b is done using str.translate, which replaces characters as indicated by a string that serves as a conversion table. Given the 100-length string ")("*50, the tables maps the first 100 ASCII values as

... Z[\]^_`abc
... )()()()()(

which takes ( -> a, ) -> b. In Python 2, conversions for all 256 ASCII values must be provided, requiring "ab"*128, one byte longer; thanks to isaacg for pointing this out.

xnor

Posted 2016-07-20T19:12:01.463

Reputation: 115 687

58Ok, that's clever. – TLW – 2016-07-21T02:03:39.563

What does the *128 do? – Erik the Outgolfer – 2016-07-22T22:17:00.130

5128 can be replaced by 50 (or 99 for that matter) to save a byte. – isaacg – 2016-07-22T23:40:55.650

@Eʀɪᴋ ᴛʜᴇ Gᴏʟғᴇʀ: I think it´s a quantifier. But I don´t really know Python and have not found any documentation on that yet. – Titus – 2016-07-23T03:02:26.140

@EʀɪᴋᴛʜᴇGᴏʟғᴇʀ https://docs.python.org/3/library/stdtypes.html#str.translate Basically, the string inside translate gets indexed with the code point of each character of the string to find the translate string. So the string )()()()()()()()... gets created, then indexed at 97 for a and 98 for b.

– isaacg – 2016-07-23T04:43:32.417

4@isaacg Thanks, I wasn't aware that changed for Python 3. – xnor – 2016-07-23T06:43:53.333

@Titus strings (https://docs.python.org/3/library/stdtypes.html#textseq) are one sequence type, so you can do all kinds of sequence operations with them (see https://docs.python.org/3/library/stdtypes.html#common-sequence-operations for details). And that is what is happening here: sequence repetition, as explained by the conversion at the end of the answer. (Other examples are "contains" checks: if "lo" in "Hello World": or iteration: for character in "my iterated string":).

– Sebastian Höffner – 2016-07-24T05:54:08.007

28

Retina, 12 bytes

Credits to FryAmTheEggman who found this solution independently.

+`a;?b
;
^;$

Prints 1 for valid input and 0 otherwise.

Try it online! (The first line enables a linefeed-separated test suite.)

Explanation

Balancing groups require expensive syntax, so instead I'm trying to reduce a valid input to a simple form.

Stage 1

+`a;?b
;

The + tells Retina to repeat this stage in a loop until the output stops changing. It matches either ab or a;b and replaces it with ;. Let's consider a few cases:

  • If the as and the bs in the string aren't balanced in the same way that ( and ) normally need to be, some a or b will remain in the string, since ba, or b;a can't be resolved and a single a or b on its own can't either. To get rid of all the as and the bs there has to be one corresponding b to the right of each a.
  • If the a and the b aren't all nested (e.g. if we have something like abab or aabaabbb) then we'll end up with multiple ; (and potentially some as and bs) because the first iteration will find multiple abs to insert them and further iterations will preserve the number of ; in the string.

Hence, if and only if the input is of the form anbn, we'll end up with a single ; in the string.

Stage 2:

^;$

Check whether the resulting string contains nothing but a single semicolon. (When I say "check" I actually mean, "count the number of matches of the given regex, but since that regex can match at most once due to the anchors, this gives either 0 or 1.)

Martin Ender

Posted 2016-07-20T19:12:01.463

Reputation: 184 808

25

Haskell, 31 bytes

f s=s==[c|c<-"ab",'a'<-s]&&s>""

The list comprehension [c|c<-"ab",'a'<-s] makes a string of one 'a' for each 'a' in s, followed by one 'b' for each 'a' in s. It avoids counting by matching on a constant and producing an output for each match.

This string is checked to be equal to the original string, and the original string is checked to be non-empty.

xnor

Posted 2016-07-20T19:12:01.463

Reputation: 115 687

This is lovely. I often forget how useful it is that Haskell orders the elements of a list comprehension in a consistent and very specific way. – Vectornaut – 2016-07-21T19:31:55.587

Much nicer than my best attempt (f=g.span id.map(=='a');g(a,b)=or a&&b==(not<$>a)) . Well done. – Jules – 2016-07-22T21:04:33.057

Wow, I didn't know one could match on a constant in a list comprehension! – rubik – 2016-07-24T07:41:05.430

16

Grime, 12 bytes

A=\aA?\b
e`A

Try it online!

Explanation

The first line defines a nonterminal A, which matches one letter a, possibly the nonterminal A, and then one letter b. The second line matches the entire input (e) against the nonterminal A.

8-byte noncompeting version

e`\a_?\b

After writing the first version of this answer, I updated Grime to consider _ as the name of the top-level expression. This solution is equivalent to the above, but avoids repeating the label A.

Zgarb

Posted 2016-07-20T19:12:01.463

Reputation: 39 083

Why didn't you do it in J? – Leaky Nun – 2016-07-20T19:38:38.860

@LeakyNun I just wanted to show off Grime. :P – Zgarb – 2016-07-20T19:39:31.060

You built this language? – Leaky Nun – 2016-07-20T19:40:12.103

@LeakyNun Yes. Development is slow, but ongoing. – Zgarb – 2016-07-20T19:41:01.620

11

Brachylog, 23 19 bytes

@2L,?lye:"ab"rz:jaL

Try it online!

Explanation

@2L,                  Split the input in two, the list containing the two halves is L
    ?lye              Take a number I between 0 and the length of the input              
        :"ab"rz       Zip the string "ab" with that number, resulting in [["a":I]:["b":I]]
               :jaL   Apply juxtapose with that zip as input and L as output
                        i.e. "a" concatenated I times to itself makes the first string of L
                        and "b" concatenated I times to itself makes the second string of L

Fatalize

Posted 2016-07-20T19:12:01.463

Reputation: 32 976

8Congratulations on getting on tryitonline.net! – Leaky Nun – 2016-07-20T20:01:24.620

10

05AB1E, 9 bytes

Code:

.M{J¹ÔQ0r

Explanation:

.M         # Get the most frequent element from the input. If the count is equal, this
           results into ['a', 'b'] or ['b', 'a'].
  {        # Sort this list, which should result into ['a', 'b'].
   J       # Join this list.
    Ô      # Connected uniquified. E.g. "aaabbb" -> "ab" and "aabbaa" -> "aba".
     Q     # Check if both strings are equal.
      0r   # (Print 0 if the input is empty).

The last two bytes can be discarded if the input is guaranteed to be non-empty.

Uses the CP-1252 encoding. Try it online!.

Adnan

Posted 2016-07-20T19:12:01.463

Reputation: 41 965

What happens with empty input? – AdmBorkBork – 2016-07-20T19:54:06.797

2Look for non-zero in the post; it’s in there :) – Lynn – 2016-07-20T20:01:08.540

@Lynn Doesn't the spec only say no-zero for a valid language though? Not about input. – Emigna – 2016-07-20T20:02:21.030

True. Thought wrong there. But you can still do .M{J¹ÔQ0r for yours. – Emigna – 2016-07-20T20:17:37.463

@Emigna Thanks, I have edited the post. – Adnan – 2016-07-20T20:20:55.473

This returns truthy for both b and a. – Magic Octopus Urn – 2019-02-26T19:12:12.117

9

J, 17 bytes

#<.(-:'ab'#~-:@#)

This works correctly for giving falsey for the empty string. Error is falsey.

Old versions:

-:'ab'#~-:@#
2&#-:'ab'#~#   NB. thanks to miles

Proof and explanation

The main verb is a fork consisting of these three verbs:

# <. (-:'ab'#~-:@#)

This means, "The lesser of (<.) the length (#) and the result of the right tine ((-:'ab'#~-:@#))".

The right tine is a 4-train, consisting of:

(-:) ('ab') (#~) (-:@#)

Let k represent our input. Then, this is equivalent to:

k -: ('ab' #~ -:@#) k

-: is the match operator, so the leading -: tests for invariance under the monadic fork 'ab' #~ -:@#.

Since the left tine of the fork is a verb, it becomes a constant function. So, the fork is equivalent to:

'ab' #~ (-:@# k)

The right tine of the fork halves (-:) the length (#) of k. Observe #:

   1 # 'ab'
'ab'
   2 # 'ab'
'aabb'
   3 # 'ab'
'aaabbb'
   'ab' #~ 3
'aaabbb'

Now, this is k only on valid inputs, so we are done here. # errors for odd-length strings, which never satisfies the language, so there we are also done.

Combined with the lesser of the length and this, the empty string, which is not a part of our language, yields its length, 0, and we are done with it all.

Conor O'Brien

Posted 2016-07-20T19:12:01.463

Reputation: 36 228

I modified it into 2&#-:'ab'#~# which should let you avoid the error and just output 0 instead while still using 12 bytes. – miles – 2016-07-20T21:33:58.583

@miles Fascinating! I never thought about it like that. – Conor O'Brien – 2016-07-20T21:39:38.330

Does this handle the empty string? – Zgarb – 2016-07-21T11:24:32.470

@Zgarb fixed it! – Conor O'Brien – 2016-07-21T19:30:19.413

9

Jelly, 6 bytes

Ṣ=Ṛ¬Pȧ

Prints the string itself if it belongs to L or is empty, and 0 otherwise.

Try it online! or verify all test cases.

How it works

Ṣ=Ṛ¬Pȧ  Main link. Argument: s (string)

Ṣ       Yield s, sorted.
  Ṛ     Yield s, reversed.
 =      Compare each character of sorted s with each character of reversed s.
   ¬    Take the logical NOT of each resulting Boolean.
    P   Take the product of the resulting Booleans.
        This will yield 1 if s ∊ L or s == "", and 0 otherwise.
     ȧ  Take the logical AND with s.
       This will replace 1 with s. Since an empty string is falsy in Jelly,
       the result is still correct if s == "".

Alternate version, 4 bytes (non-competing)

ṢnṚȦ

Prints 1 or 0. Try it online! or verify all test cases.

How it works

ṢnṚȦ  Main link. Argument: s (string)

Ṣ     Yield s, sorted.
  Ṛ   Yield s, reversed.
 n    Compare each character of the results, returning 1 iff they're not equal.
   Ȧ  All (Octave-style truthy); return 1 if the list is non-empty and all numbers
      are non-zero, 0 in all other cases.

Dennis

Posted 2016-07-20T19:12:01.463

Reputation: 196 637

9

Bison/YACC 60 (or 29) bytes

(Well, the compilation for a YACC program is a couple of steps so might want to include some for that. See below for details.)

%%
l:c'\n';
c:'a''b'|'a'c'b';
%%
yylex(){return getchar();}

The function should be fairly obvious if you know to interpret it in terms of a formal grammar. The parser accepts either ab or an a followed by any acceptable sequence followed by a b.

This implementation relies on a compiler that accepts K&R semantics to lose a few characters.

It's wordier than I would like with the need to define yylex and to call getchar.

Compile with

$ yacc equal.yacc
$ gcc -m64 --std=c89 y.tab.c -o equal -L/usr/local/opt/bison/lib/ -ly

(most of the options to gcc are specific to my system and shouldn't count against the byte count; you might want to count -std=c89 which adds 8 to the value listed).

Run with

$ echo "aabb" | ./equal

or equivalent.

The truth value is returned to the the OS and errors also report syntax error to the command line. If I can count only the part of the code that defines the parsing function (that is neglect the second %% and all that follows) I get a count of 29 bytes.

dmckee --- ex-moderator kitten

Posted 2016-07-20T19:12:01.463

Reputation: 2 726

7

JavaScript, 54 55 44

s=>s&&s.match(`^a{${l=s.length/2}}b{${l}}$`)

Builds a simple regex based on the length of the string and tests it. For a length 4 string (aabb) the regex looks like: ^a{2}b{2}$

Returns a truthy or falsey value.

11 bytes saved thanks to Neil.

f=s=>s&&s.match(`^a{${l=s.length/2}}b{${l}}$`)
// true
console.log(f('ab'), !!f('ab'))
console.log(f('aabb'), !!f('aabb'))
console.log(f('aaaaabbbbb'), !!f('aaaaabbbbb'))
// false
console.log(f('a'), !!f('a'))
console.log(f('b'), !!f('b'))
console.log(f('ba'), !!f('ba'))
console.log(f('aaab'), !!f('aaab'))
console.log(f('ababab'), !!f('ababab'))
console.log(f('c'), !!f('c'))
console.log(f('abc'), !!f('abc'))
console.log(f(''), !!f(''))

Scimonster

Posted 2016-07-20T19:12:01.463

Reputation: 2 905

The f= can be omitted. – Leaky Nun – 2016-07-20T19:53:53.917

Is a function expression a valid submission, or must it actually be, ahem, functional? – Scimonster – 2016-07-20T19:54:34.720

A function is a valid submission. – Leaky Nun – 2016-07-20T19:56:42.777

@TimmyD It used to return true, but now it returns false. – Scimonster – 2016-07-20T20:06:28.863

s.match will turn your string into a regexp for you. Also, I think using a template string might save you a couple of bytes. – Neil – 2016-07-20T20:09:17.733

@Neil Thanks! Didn't realize that about s.match. – Scimonster – 2016-07-20T20:19:40.303

Using RegExp to match for an irregular language :>) so evil – Derek 朕會功夫 – 2016-07-24T00:09:40.627

1s=>s.match(`^a{${s.length/2}}b+$`)? – l4m2 – 2018-05-30T04:36:00.843

7

Perl 5.10, 35 17 bytes (with -n flag)

say/^(a(?1)?b)$/

Ensures that the string starts with as and then recurses on bs. It matches only if both lengths are equal.

Thanks to Martin Ender for halving the byte count and teaching me a little about recursion in regexes :D

It returns the whole string if it matches, and nothing if not.

Try it here!

Paul Picard

Posted 2016-07-20T19:12:01.463

Reputation: 863

Closest I can manage including the non-empty test case is 18 bytes: $_&&=y/a//==y/b// (requires -p), without the empty you could drop the && for 16! So close... – Dom Hastings – 2016-07-21T09:08:54.697

1So I can do another 17 bytes: echo -n 'aaabbb'|perl -pe '$_+=y/a//==y/b//' but I can't shift another byte... Might have to give up on this! – Dom Hastings – 2016-07-22T15:33:46.107

5

C, 57 53 Bytes

t;x(char*s){t+=*s%2*2;return--t?*s&&x(s+1):*s*!1[s];}

Old 57 bytes long solution:

t;x(char*s){*s&1&&(t+=2);return--t?*s&&x(s+1):*s&&!1[s];}

Compiled with gcc v. 4.8.2 @Ubuntu

Thanks ugoren for tips!

Try it on Ideone!

Jasmes

Posted 2016-07-20T19:12:01.463

Reputation: 131

Since I'm new here and can't comment on other answers yet, I just want to point out that 62b solution from @Josh gives false positive on strings like "aaabab". – Jasmes – 2016-07-22T15:47:32.397

Change (t+=2) to t++++ for -1 byte. – owacoder – 2016-07-25T13:20:40.543

1@owacoder t++++ is not a valid C code. – Jasmes – 2016-07-25T14:21:45.107

Save some with t+=*s%2*2 and :*s*!1[s] – ugoren – 2016-07-31T14:18:58.390

Very clever answer! It does unfortunately fail on input "ba" : http://ideone.com/yxixG2

– Josh – 2016-08-08T15:07:36.230

4

Retina, 22 bytes

Another shorter answer in the same language just came...

^(a)+(?<-1>b)+(?(1)c)$

Try it online!

This is a showcase of the balancing groups in regex, which is explained fully by Martin Ender.

As my explanation would not come close to half of it, I'll just link to it and not attempt to explain, as that would be detrimental to the glory of his explanation.

Leaky Nun

Posted 2016-07-20T19:12:01.463

Reputation: 45 011

4

Befunge-93, 67 bytes

0v@.<  0<@.!-$<  >0\v
+>~:0`!#^_:"a" -#^_$ 1
~+1_^#!-"b" _ ^#`0: <

Try it here! Might explain how it works later. Might also try to golf it just a tad bit more, just for kicks.

user55852

Posted 2016-07-20T19:12:01.463

Reputation:

3

Japt, 11 bytes

©¬n eȦUg~Y

Try it online!

Gives either true or false, except that "" gives "" which is falsy in JS.

Unpacked & How it works

U&&Uq n eXYZ{X!=Ug~Y

U&&     The input string is not empty, and...
Uq n    Convert to array of chars and sort
eXYZ{   Does every element satisfy...?
X!=       The sorted char does not equal...
Ug~Y      the char at the same position on the original string reversed

Adopted from Dennis' MATL solution.

Bubbler

Posted 2016-07-20T19:12:01.463

Reputation: 16 616

3

C, 69 bytes

69 bytes:

#define f(s)strlen(s)==2*strcspn(s,"b")&strrchr(s,97)+1==strchr(s,98)

For those unfamiliar:

  • strlen determines the length of the string
  • strcspn returns the first index in string where the other string is found
  • strchr returns a pointer to the first occurrence of a character
  • strrchr returns a pointer to the last occurrence of a character

A big thanks to Titus!

Josh

Posted 2016-07-20T19:12:01.463

Reputation: 2 783

1save one byte with >97 instead of ==98 – Titus – 2016-07-23T02:02:21.827

2

61 bytes solution gives false positive on strings like "aaabab". See http://ideone.com/nmT8rm

– Jasmes – 2016-07-28T16:36:36.703

Ah you are correct Jasmes, thanks. I will have to rethink this a little. – Josh – 2016-07-28T17:30:45.467

Reverting back to the 69 byte solution, not sure if I can get any shorter using this approach. – Josh – 2016-07-28T19:45:50.067

3

MATL, 9 bytes

vHI$e!d1=

Try it online!

The output array is truthy if it is non-empty and all its entries are nonzero. Otherwise it's falsy. Here are some examples.

v     % concatenate the stack. Since it's empty, pushes the empty array, []
H     % push 2
I$    % specify three inputs for next function
e     % reshape(input, [], 2): this takes the input implicitly and reshapes it in 2
      % columns in column major order. If the input has odd length a zero is padded at
      % the end. For input 'aaabbb' this gives the 2D char array ['ab;'ab';'ab']
!     % transpose. This gives ['aaa;'bbb']
d     % difference along each column
1=    % test if all elements are 1. If so, that means the first tow contains 'a' and
      % the second 'b'. Implicitly display

Luis Mendo

Posted 2016-07-20T19:12:01.463

Reputation: 87 464

2That's some convenient definition of truthy. (I knew about the non-zero requirement, but not about the non-empty one.) – Dennis – 2016-07-21T00:34:10.367

3

JavaScript, 44 42

Crossed out 44 is still regular 44 ;(

f=s=>(z=s.match`^a(.+)b$`)?f(z[1]):s=="ab"

Works by recursively stripping off the outer a and b and recursively using the inner value selected but .+. When there's no match on ^a.+b$ left, then the final result is whether the remaining string is the exact value ab.

Test cases:

console.log(["ab","aabb","aaabbb","aaaabbbb","aaaaabbbbb","aaaaaabbbbbb"].every(f) == true)
console.log(["","a","b","aa","ba","bb","aaa","aab","aba","abb","baa","bab","bba","bbb","aaaa","aaab","aaba","abaa","abab","abba","abbb","baaa","baab","baba","babb","bbaa","bbab","bbba","bbbb"].some(f) == false)

apsillers

Posted 2016-07-20T19:12:01.463

Reputation: 3 632

3

x86 machine code, 29 27 bytes

Hexdump:

33 c0 40 41 80 79 ff 61 74 f8 48 41 80 79 fe 62
74 f8 0a 41 fe f7 d8 1b c0 40 c3

Assembly code:

    xor eax, eax;
loop1:
    inc eax;
    inc ecx;
    cmp byte ptr [ecx-1], 'a';
    je loop1;

loop2:
    dec eax;
    inc ecx;
    cmp byte ptr [ecx-2], 'b';
    je loop2;

    or al, [ecx-2];
    neg eax;
    sbb eax, eax;
    inc eax;
done:
    ret;

Iterates over the a bytes in the beginning, then over the following 'b' bytes. The first loop increases a counter, and the second loop decreases it. Afterwards, does a bitwise OR between the following conditions:

  1. If the counter is not 0 at the end, the string doesn't match
  2. If the byte that follows the sequence of bs is not 0, the string also doesn't match

Then, it has to "invert" the truth value in eax - set it to 0 if it was not 0, and vice versa. It turns out that the shortest code to do that is the following 5-byte code, which I stole from the output of my C++ compiler for result = (result == 0):

    neg eax;      // negate eax; set C flag to 1 if it was nonzero
    sbb eax, eax; // subtract eax and the C flag from eax
    inc eax;      // increase eax

anatolyg

Posted 2016-07-20T19:12:01.463

Reputation: 10 719

1

I think you can improve your negation. Try: neg eax to set the carry flag as before, cmc to invert the carry flag and salc to set AL to FFh or 0 depending on whether the carry flag is set or not. Saves 2 bytes, although does end up with an 8-bit result rather than 32-bit.

– Jules – 2016-07-22T21:40:43.433

The same thing using string ops, with ESI pointing to the input string, and returning the result in AL (uses SETcc, requires 386+): xor eax,eax | xor ecx,ecx | l1: inc ecx | lodsb | cmp al, 'a' | jz l1 | dec esi | l2: lodsb | cmp al,'b' | loopz l2 | or eax,ecx | setz al | ret – ninjalj – 2016-07-26T21:26:11.760

@ninjalj You should post that in an answer - it's sufficiently different from mine, and I suspect is significantly shorter! – anatolyg – 2016-07-26T22:02:25.117

3

Ruby, 24 bytes

eval(gets.tr'ab','[]')*1

(This is just xnor's brilliant idea in Ruby form. My other answer is a solution I actually came up with myself.)

The program takes the input, transforms a and b to [ and ] respectively, and evaluates it.

Valid input will form a nested array, and nothing happens. An unbalanced expression will make the program crash. In Ruby empty input is evaluated as nil, which will crash because nil has not defined a * method.

daniero

Posted 2016-07-20T19:12:01.463

Reputation: 17 193

3

R, 64 61 55 bytes, 73 67 bytes (robust) or 46 bytes (if empty strings are allowed)

  1. Again, xnor's answer reworked. If it is implied by the rules that the input will consist of a string of as and bs, it should work: returns NULL if the expression is valid, throws and error or nothing otherwise.

    if((y<-scan(,''))>'')eval(parse(t=chartr('ab','{}',y)))
    
  2. If the input is not robust and may contain some garbage, e.g. aa3bb, then the following version should be considered (must return TRUE for true test cases, not NULL):

    if(length(y<-scan(,'')))is.null(eval(parse(t=chartr("ab","{}",y))))
    
  3. Finally, if empty strings are allowed, we can ignore the condition for non-empty input:

    eval(parse(text=chartr("ab","{}",scan(,''))))
    

    Again, NULL if success, anything else otherwise.

Andreï Kostyrka

Posted 2016-07-20T19:12:01.463

Reputation: 1 389

I don´t know R, what´s your result for empty input? (should be falsy) – Titus – 2016-07-23T02:35:13.997

Is there really no shorter way to test for empty input? – Titus – 2016-07-25T06:58:36.260

Version 1: just nothing (correct input returns only NULL), version 2: just nothing (correct input returns only TRUE), version 3 (assuming empty strings are OK, as state): NULL. R is a statistical object-oriented language that typecasts everything just OK, without any warning. – Andreï Kostyrka – 2016-07-26T11:24:08.967

This (answer 1) can be further improved to 55 bytes: if((y<-scan(,''))>'')eval(parse(t=chartr('ab','{}',y))) – Giuseppe – 2017-08-04T14:01:16.077

3

Sed, 38 + 2 = 40 bytes

s/.*/c&d/;:x;s/ca(.*)bd/c\1d/;tx;/cd/p

A non empty string output is truthy

Finite state automata can not do this, you say? What about finite state automata with loops. :P

Run with r and n flags.

Explanation

s/.*/c&d/        #Wrap the input in 'c' and 'd' (used as markers)
:x               #Define a label named 'x'
s/ca(.*)bd/c\1d/ #Deletes 'a's preceded by 'c's and equivalently for 'b's and 'd's. This shifts the markers to the center
tx               #If the previous substitution was made, jump to label x
/cd/p            #If the markers are next to one another, print the string

someonewithpc

Posted 2016-07-20T19:12:01.463

Reputation: 191

Nice approach. Thanks for the breakdown. – joeytwiddle – 2016-07-25T03:28:31.677

3

ANTLR, 31 bytes

grammar A;r:'ab'|'a'r'b'|r'\n';

Uses the same concept as @dmckee's YACC answer, just slightly more golfed.

To test, follow the steps in ANTLR's Getting Started tutorial. Then, put the above code into a file named A.g4 and run these commands:

$ antlr A.g4
$ javac A*.java

Then test by giving input on STDIN to grun A r like so:

$ echo "aaabbb" | grun A r

If the input is valid, nothing will be output; if it is invalid, grun will give an error (either token recognition error, extraneous input, mismatched input, or no viable alternative).

Example usage:

$ echo "aabb" | grun A r
$ echo "abbb" | grun A r
line 1:2 mismatched input 'b' expecting {<EOF>, '
'}

Copper

Posted 2016-07-20T19:12:01.463

Reputation: 3 684

Clever trick adding the newline as an alternate in a single rule. I think I could save a few that way in yacc, too. The grammer keyword is a stinker for golfing with antlr, though. Kinda like using fortran.

– dmckee --- ex-moderator kitten – 2016-07-28T16:15:05.253

2

Cubically, 109 98 70 60 bytes

+52/1+55~=7!6&(:7UR'UF'D2~=7)6>7?6&(:7D2FU'RU'~=7)6>7!6&!8%6

-11 bytes thanks to TehPers

-10 bytes thanks to new language feature

Try it online!

Prints 1 if the string matches L, otherwise prints nothing.

Explanation:

+52/1+55            Sets the notepad to 97 ('a')
        ~           takes input
         =7!6&      exits if input is not 'a'

(             )6    While the notepad is truthy
 :7                 Save the current character value
   UR'UF'D2         Perform a cube operation
           ~=7      Set notepad to true if next character is the same

>7?6&               Exit if next character is end of input (-1)

(             )6    While the notepad is truthy
 :7                 Save the current character
   D2FU'RU'         Reverse one iteration of the previous operation
            ~=7     Set notepad to true if next character is the same

>7!6&               Exit if next character is NOT end of input
!8%6                Print 1 if the cube is solved

The looping operation has been replaced with a new sequence with a period of 1260, which will still never give a false negative but now is guaranteed to work for inputs of less than 1260 characters.

I've replaced the previous check for solved cube with !8%6. 8 is a recently added pseudo-face which is always equal to "Is the cube solved?" so I can just branch on that directly.

Kamil Drakari

Posted 2016-07-20T19:12:01.463

Reputation: 3 461

Why not do -6>7?6& instead of -6>7!6{...}? Also, couldn't you replace -6+111=3!6& with -6+21=3!6&, -6+1111=4!6& with -6+22=4!6&, and -6+11111=5!6& with -6+32=5!6&? You checked those faces earlier in the program. Also, you can replace -6=0!6& with -6>0?6& and remove the next -6 because 0 isn't greater than 0. Rather than =#!6&-6..., try =#0?6&.... I'm also pretty sure you can remove one or two of those checks, but I'm not a mathematician. I had a solution similar to this in mind, but I didn't think to compare the notepad to the previous value. Nice job! – TehPers – 2017-08-07T21:10:00.493

Also, you can remove the -6 in -6=0!6& because to exit the loop before it, the notepad must be 0. – TehPers – 2017-08-07T21:15:02.383

2

Brachylog (newer), 11 10 6 bytes

o?ḅĊlᵛ

Try it online!

The predicate succeeds if the input is in L and fails otherwise.

          The input
o         sorted
 ?        is the input,
  ḅ       and the runs in the input
   Ċ      of which there are two
    lᵛ    have the same length.

Unrelated String

Posted 2016-07-20T19:12:01.463

Reputation: 5 300

1At this rate you will catch up to my number of Brachylog answers in a few days! – Fatalize – 2019-03-01T12:17:59.553

2

Nearly 5 months later, decided to come back to my first answer here to see if I could golf it more. Here's the results!

Zsh, 28 bytes

eval ${${${1:?}//a/( }//b/)}

Just as I posted my 29 byte answer, I thought "what about if we handle the empty case specially?" Turns out, it's one byte shorter! Try it online!

Successful cases: ( ( ( ... ( ( ))...))).

Unsuccessful cases:

  • Unmatched/uneven parens: obviously fails
  • /ba/ case: ( )( ) is a "parse error" in the eval, but gives unknown file attribute: if run directly.
  • Empty case: ${1:?} handles exactly this.

Zsh, 29 bytes

eval \(${${1//a/(+}//b/+i)}\)

Try it online!

Same "eval matching delimiters" principle, but this time using math mode instead of parameter expansions:

eval \(${${1//a/(+}//b/+i)}\)
     \(                    \)   # literal ( )
         ${1//a/(+}             # replace 'a' with '(+'
       ${          //b/+i)}     # replace 'b' with '+i)'

A successful result looks like: ((+(+(...+(++i)+...i)+i)+i)), incrementing i to 1 and adding it repeatedly. This will result in a positive integer, which (( )) evaluates truthy.

An unsuccessful result looks like one of the following:

  • Uneven/unmatched parens (obviously fails)
  • /^b(a{n}b{n})?a$/ case: (+i)(...)(+) fails with "missing identifier after +"
  • Any other /ba/ case: (...)(...) errors in math mode
  • Empty case: () is an anonymous function with no body, and errors

Original answer:

Zsh, 35 bytes

eval '${'${${1//a/'${'}//b/'}'}'#}'

Try it online! (More examples)

Inspired by xnor's post, this outputs via exit code. Zsh will happlily handle nested ${}s, but will err on ${${...}${...}} or unmatched braces. There are two caveats which makes this longer:

  • We need the outer ${...}, since ${}${} is valid zsh.
  • We need a # at then end, which causes an error when the input is the empty string:
    • ${${}#} is prefix removal, which is fine.
    • ${#} evaluates to the number of parameters, which will be an integer and not a valid command.

GammaFunction

Posted 2016-07-20T19:12:01.463

Reputation: 2 838

1Welcome to PPCG! Nice first answer – Jo King – 2019-03-21T03:23:23.933

2

C (Ansi), 65 75 Bytes

Golfed:

l(b,i,j,k)char*b;{for(i=j=0;(k=b[i++])>0&k<=b[i];)j+=2*(k>97)-1;return !j;}

Explanation:

Sets a value j and increments j on each b and decrements j on anything else. Checked if the letter before is less than or equal the next letter so prevent abab from working

Edits

Added checks for abab cases.

dj0wns

Posted 2016-07-20T19:12:01.463

Reputation: 328

Won't this give false positives on strings like ba or abab? – Zgarb – 2016-07-20T19:43:53.983

Ahh yes, I misread the post since I could not see the picture since its blocked for me. Fixing it! – dj0wns – 2016-07-20T19:50:36.087

2

Python, 43 40 Bytes

lambda s:''<s==len(s)/2*"a"+len(s)/2*"b"

connsidered the obvious solution thanks to Leaky Nun

other idea, 45 bytes:

lambda s:s and list(s)==sorted(len(s)/2*"ab")

-4 bytes by using len/2 (i get an error when the half comes last)

now gives false for the empty string

-3 bytes thanks to xnor

KarlKastor

Posted 2016-07-20T19:12:01.463

Reputation: 2 352

Yes, lambdas don't have to be named. – Leaky Nun – 2016-07-20T19:51:26.480

lambda s:list(s)==sorted("ab"*len(s)//2) (Python 3) – Leaky Nun – 2016-07-20T19:52:10.400

lambda s:s=="a"*len(s)//2+"b"*len(s)//2 (Python 3) – Leaky Nun – 2016-07-20T19:52:42.213

yeah, I realized that while posting it. lol, the obvious solution is shorter in Python 2: – KarlKastor – 2016-07-20T19:57:40.797

lambda s:s=="a"*len(s)/2+"b"*len(s)/2 if you accept errors as falsey – Leaky Nun – 2016-07-20T19:58:21.557

lambda s:s==len(s)/2*"a"+len(s)/2*"b" # (Python 2, no errors) – KarlKastor – 2016-07-20T19:59:04.257

What happens with empty input? – AdmBorkBork – 2016-07-20T20:01:53.180

Doesn't this incorrectly give True for the empty string? – Zgarb – 2016-07-20T20:03:48.713

it's true, damn have to change that – KarlKastor – 2016-07-20T20:03:51.483

fix: but there has to be a shorter way: lambda s:s and s==len(s)/2*"a"+len(s)/2*"b" – KarlKastor – 2016-07-20T20:07:21.883

1You can do ''< instead of s and to rule out the empty case. – xnor – 2016-07-20T22:54:36.160

2

Batch, 133 bytes

@if ""=="%1" exit/b1        Fail if the input is empty
@set a=%1                   Grab the input into a variable for processing
@set b=%a:ab=%              Remove all `ab` substrings
@if "%a%"=="%b%" exit/b1    Fail if we didn't remove anything
@if not %a%==a%b%b exit/b1  Fail if we removed more than one `ab`
@if ""=="%b%" exit/b0       Success if there's nothing left to check
@%0 %b%                     Rinse and repeat

Returns an ERRORLEVEL of 0 on success, 1 on failure. Batch doesn't like to do substring replacement on empty strings, so we have to check that up front; if an empty parameter was legal, line 6 wouldn't be necessary.

Neil

Posted 2016-07-20T19:12:01.463

Reputation: 95 035

2

PowerShell v2+, 61 52 bytes

param($n)$x=$n.length/2;$n-and$n-match"^a{$x}b{$x}$"

Takes input $n as a string, creates $x as half the length. Constructions an -and Boolean comparison between $n and a -match regex operator against the regex of an equal number of a's and b's. Outputs Boolean $TRUE or $FALSE. The $n-and is there to account for ""=$FALSE.

Alternate, 35 bytes

$args-match'^(a)+(?<-1>b)+(?(1)c)$'

This uses the regex from Leaky's answer, based on .NET balancing groups, just encapsulated in the PowerShell -match operator. Returns the string for truthy, or empty string for falsey.

AdmBorkBork

Posted 2016-07-20T19:12:01.463

Reputation: 41 581

In the alternate version you should evaluate -match against $args[0], otherwise -match will work as a filter – Mathias R. Jessen – 2016-07-24T18:18:31.383

@MathiasR.Jessen In production code, yes, but we can golf the [0] here because we're only given one input and we only need one truthy/falsey value as output. Since an empty string is falsey and a non-empty string is truthy, we can filter against the array and either get the input string back or nothing back, which satisfies the challenge requirements. – AdmBorkBork – 2016-07-25T12:30:08.687

2

Pyth - 13 bytes

&zqzS*/lz2"ab

Explained:

  qz          #is input equal to
          "ab #the string "ab"
     *        #multiplied by
      /lz2    #length of input / 2
    S         #and sorted?
&z            #(implicitly) print if the above is true and z is not empty

Cowabunghole

Posted 2016-07-20T19:12:01.463

Reputation: 1 590

You can use a string as input and then make it &qS*/lQ2"ab – Leaky Nun – 2016-07-20T20:25:39.437

@LeakyNun thanks for the tip! Can you explain how/why that works? This is my first time ever using Pyth – Cowabunghole – 2016-07-20T20:46:37.697

For example, +4 will expand to +4Q (implicit filling of arguments) – Leaky Nun – 2016-07-21T04:07:52.027

2

Haskell, 39 bytes

p x=elem x$scanl(\s _->'a':s++"b")"ab"x

Usage example: p "aabb" -> True.

scanl(\s _->'a':s++"b")"ab"x build a list of all ["ab", "aabb", "aaabbb", ...] with a total of (length x) elements. elem checks if x is in this list.

nimi

Posted 2016-07-20T19:12:01.463

Reputation: 34 639

2

C, 65 bytes

m,t;C(char*c){for(m=1,t=0;*c;)m>0&*c++-97&&(m-=2),t+=m;return!t;}

Stefano Sanfilippo

Posted 2016-07-20T19:12:01.463

Reputation: 1 059

m---- doesn't compile. – ugoren – 2016-07-31T14:33:35.750

@ugoren what compiler are you using? – Stefano Sanfilippo – 2016-08-08T09:31:49.067

gcc on Linux says error: invalid lvalue in decrement. Does any compiler compile this? – ugoren – 2016-08-08T14:56:11.247

Whoopsie, correct, nice catch @ugoren, I must have missed the error among the warnings. Reverted to the 65 byte solution. – Stefano Sanfilippo – 2016-08-10T09:09:31.787

2

Octave, 28 bytes

@(m)diff(+m)>=0&~sum(m-97.5)

This defines an anonymous function. It works also for empty input. Falsy and truthy are as described in my MATL answer.

Try it at ideone.

Explanation

diff(+m)>0 checks if the input string (consisting of 'a' and 'b') is sorted, that is, all characters 'a' come before all 'b'.

The other condition that needs to be checked is whether the numbers of characters 'a' and 'b' are the same. Since their ASCII codes are 97 ansd 98, this is done subtracting 97.5 and chacking if the the sum is zero.

For empty input the result is empty, which is falsy.

Luis Mendo

Posted 2016-07-20T19:12:01.463

Reputation: 87 464

2

Mathematica 83 80 68 54 bytes

#&@@@#<>""=="ab"&&Equal@@Length/@#&@*Split@*Characters

Thanks @MartinEnder for shortening it by 26 bytes :)

If input can be a list of characters instead of a string, 39 bytes is possible:

#&@@@#=={a,b}&&Equal@@Length/@#&@*Split

eg:

#&@@@#=={a,b}&&Equal@@Length/@#&@*Split@{a,b,a,b,a,b}

(*False*)

martin

Posted 2016-07-20T19:12:01.463

Reputation: 1 335

1It's probably shortest with a recursive regex: #~StringMatchQ~RegularExpression@"(a(?1)?b)"& – Martin Ender – 2016-07-21T09:41:06.657

@MartinEnder Ah yes - much better - I'll delete & let you post that, since it doesn't resemble my awful attemp in the slightest! – martin – 2016-07-21T09:43:24.240

1No, don't delete yours. A regex-less solution is still interesting. :) – Martin Ender – 2016-07-21T09:43:47.047

2

Mathematica, 45 bytes

#~StringMatchQ~RegularExpression@"(a(?1)?b)"&

Another recursive regex solution. This doesn't need anchors because StringMatchQ achors it implicitly, but unfortunately it just seems to do wrap the regex in ^(?:...)$ which means we can't use (?R) for the recursion, as that gets the anchors as well. Hence the seemingly useless group around the entire regex, so we can access only that part for the recursion.

Martin Ender

Posted 2016-07-20T19:12:01.463

Reputation: 184 808

2

JavaScript, 34 bytes

s=>(s=s.match`^a(.*)b$`[1])?f(s):1

In true automata fashion, this function returns 1 if it's true, and fails if it's not.

f=s=>(s=s.match`^a(.*)b$`[1])?f(s):1

let test_strings = ["ab", "aabb", "", "a", "abb", "abc", "abab", "abba"];
test_strings.map(s => {
try {console.log("f(\"" + s + "\") returned " + f(s));}
catch(e) {console.log("f(\"" + s + "\") threw " + e);}
});

Yay295

Posted 2016-07-20T19:12:01.463

Reputation: 650

2

Excel, 55 bytes

=AND(A1<>"",A1=REPT("a",LEN(A1)/2)&REPT("b",LEN(A1)/2))

Test string in cell A1, formula above in any other cell. Generates a comparison string of the appropriate length and checks for a match. Shows TRUE or FALSE as appropriate.

Joffan

Posted 2016-07-20T19:12:01.463

Reputation: 832

2

PHP, 61 40 bytes

new approach inspired by Didz´ answer: regexp with a recursive pattern

<?=preg_match('#^(a(?1)?b)$#',$argv[1]);

P.S.: I see now that I am not the first one with this pattern. You never stop learning.


Josh´s C solution translated to PHP comes at the same size (with one byte lost in translation, one byte golfed for PHP with bitwise and, one byte golfed for C and PHP):

<?=strlen($s=$argv[1])==2*strspn($s,a)&$s[strrpos($s,a)+1]>a; (61 bytes)


My second own approach, a little longer: build a string with (input length / 2) of a, one of b and compare the concatenation to input:
<?=str_repeat(a,$n=strlen($s=$argv[1])/2).str_repeat(b,$n)==$s; (63 bytes)
Could save 3 bytes on that if I could use ($r=str_repeat) for a function call directly ... if.


all versions:

  • take the string as argument from cli
  • print 1 for true, nothing for false

testing

  • replace <?= with <?function f($s){return
  • remove =$argv[1] (or replace $argv[1] with $s)
  • append } and my test suite (below)
  • call in a web browser

function out($a){if(is_object($a)){foreach($a as$v)$r[]=$v;return'{'.implode(',',$r).'}';}if(!is_array($a))return$a;$r=[];foreach($a as$v)$r[]=out($v);return'['.join(',',$r).']';}
function test($x,$e,$y){static $h='<table border=1><tr><th>input</th><th>output</th><th>expected</th><th>ok?</th></tr>';echo"$h<tr><td>",out($x),'</td><td>',out($y),'</td><td>',out($e),'</td><td>',$e==$y?'Y':'N',"</td></tr>";$h='';}
$cases=[
    1=>[ab,aabb,aaabbb,aaaabbbb,aaaaabbbbb,aaaaaabbbbbb],
    0=>['',a,b,aa,ba,bb,aaa,aab,aba,abb,baa,bab,bba,bbb,aaaa,aaab,aaba,
        abaa,abab,abba,abbb,baaa,baab,baba,babb,bbaa,bbab,bbba,bbbb]
];
foreach($cases as$e=>$a)foreach($a as$x)test($x,$e,f($x)|0);

Titus

Posted 2016-07-20T19:12:01.463

Reputation: 13 814

1

Brainfuck, 77 bytes

,
[
  [
    >+[>+<-]<<
    ,[>->+<<-]
    >[<<]
    >
  ]
  >+[<<]
  >
  [
    >-[>+<-]<<
    ,
    [
      [>->+<<-]
      >[<<]
      <
    ]
    >>
  ]
  +>[<]
]
<.

Expects input without a trailing newline. Outputs \x00 for false and \x01 for true.

Try it online.

The idea is to increment n for initial a characters and decrement n for subsequent b characters and then check whether n is zero at the end, short-circuiting to print false if the input does not match /^a+b+$/. Since the input is guaranteed to match /^[ab]*$/, we can ignore the fact that ord('a') = 97 and just use ord('b') = ord('a') + 1 to check for /^a+b/.

Mitch Schwartz

Posted 2016-07-20T19:12:01.463

Reputation: 4 899

1

awk, 53 bytes

Solution forms pairs from the assumed beginning of as (i) and bs ((NF+1)/2)and iterates towards a's ending. Truth value is kept in a anding it with result of comparing the current pair ($i$(i+j)) to ab.

{for(a=j=++NF/2;++i<=j;)t=t&&($i$(i+j)=="ab");exit t}

Run it:

$ echo abab|awk -F '' '{for(a=j=++NF/2;++i<=j;)t=t&&($i$(i+j)=="ab");exit t}'
$ echo $?
0
$ echo aabb|awk -F '' '{for(a=j=++NF/2;++i<=j;)t=t&&($i$(i+j)=="ab");exit t}'
$ echo $?
1

James Brown

Posted 2016-07-20T19:12:01.463

Reputation: 663

1

Prolog (SWI), 34 33 bytes

-[].
-L:-append([97|M],`b`,L),-M.

Try it online!

ASCII-only

Posted 2016-07-20T19:12:01.463

Reputation: 4 687

1

SmileBASIC 3, 38 bytes

INPUT V$L=LEN(V$)/2?"a"*L+"b"*L==V$&&L

For all integers n > 2 there is only one valid string in this language. So we build that string, given the length of the input, and check if it equals the input. Prints 0 if false, 1 if true (SB truthiness convention.)

INPUT V$     'read line from console, store in V$
L=LEN(V$)/2  'number of As/Bs in valid string (length of input / 2)

?                    'print
 "a"*L+"b"*L         'valid A/B string for given length
            ==       'equals
              V$     'input
                &&   'and
                  L  'length is non-zero

snail_

Posted 2016-07-20T19:12:01.463

Reputation: 1 982

1

Perl 6, 25 bytes

{$_&&try !TR/ab/()/.EVAL}

Try it online!

Port of xnor's answer that returns True and Nil or an empty string. This translates all abs to the characters () and EVALs it. If there are unmatched parenthesises like aaab or ba, it errors. If there are two pairs of ab in a row, that errors as ()() is attempting a function call on an empty list. Otherwise, it returns an empty list (), which we then Boolean not (!) to get a truthy value. The try swallows the errors and returns Nil instead. If the input is empty, then it returns the empty string.

Jo King

Posted 2016-07-20T19:12:01.463

Reputation: 38 234

1

PowerShell, 39 bytes

$args-in($args|% t*y|%{($r="a$r"+'b')})

Try it online!


PowerShell 5.1, 37 bytes

$args-in($args|% t*y|%{($r="a$r`b")})

mazzy

Posted 2016-07-20T19:12:01.463

Reputation: 4 832

1

Ruby, 17 bytes (16 + '-n' flag)

p~/^(a\g<1>?b)$/

Try it online!

The recursive regex solution ported to ruby.

G B

Posted 2016-07-20T19:12:01.463

Reputation: 11 099

1

Burlesque, 21 bytes

Jsojgwsa2==j)-]sm&&&&

Try it online!

Jso   #(Non-destructive) is sorted?
jgw   #Group like elements, prepend with length of group
sa2== #2 distinct elements
j)-]  #Take the lengths
sm    #Are the same
&&&&  #All are true

DeathIncarnate

Posted 2016-07-20T19:12:01.463

Reputation: 916

1

///, 13 bytes

/$a/$$//$b//$

Input is hard-coded at the end of the program since Slashes doesn't have input. Outputs only "$" for a truthy value and something else otherwise.

Try it online!

EdgyNerd

Posted 2016-07-20T19:12:01.463

Reputation: 1 106

1

Pyke, 10 bytes

le"ab"*Sq&

Try it here!

Or 9 bytes if null input isn't valid

le"ab"*Sq

Blue

Posted 2016-07-20T19:12:01.463

Reputation: 26 661

1

Java 7, 69 bytes

 boolean c(String i){return i.matches("(?x)(?:a(?=a*(\\1?+b)))+\\1");}

Regex shamelessly 'borrowed' from here.

Full code & test cases:

Try it here (with all test cases).

class Main{
  static boolean c(String i){
    return i.matches("(?x)(?:a(?=a*(\\1?+b)))+\\1");
  }

  public static void main(String[] a){
    System.out.println(c("ab"));
    System.out.println(c("aabb"));
    System.out.println(c("aaabbb"));
    System.out.println(c("aaaabbbb"));
    System.out.println(c("aaaaabbbbb"));

    System.out.println(c(""));
    System.out.println(c("a"));
    System.out.println(c("b"));
    System.out.println(c("aa"));
    System.out.println(c("ba"));
    System.out.println(c("bb"));
    System.out.println(c("aba"));
    System.out.println(c("abab"));
    System.out.println(c("abba"));
    System.out.println(c("bbaa"));
    System.out.println(c("bbbb"));
  }
}

Output:

true
true
true
true
true
false
false
false
false
false
false
false
false
false
false
false

Kevin Cruijssen

Posted 2016-07-20T19:12:01.463

Reputation: 67 575

1

Ruby, 33 bytes

Try it online

->s{s==?a*(l=s.size/2)+?b*l&&l>0}

Value Ink

Posted 2016-07-20T19:12:01.463

Reputation: 10 608

1

Ruby, 31 bytes

Aw, that poor syntax highlighter :)

->s{s=~/^a+/&&$&.tr(?a,?b)==$'}

Does s begin with one or more a? Is also that bunch of as ($&) the same as the rest of the string ($') if we replace all those as with bs?

test here

daniero

Posted 2016-07-20T19:12:01.463

Reputation: 17 193

1

Racket, 91 bytes

(λ(x)((λ(y)(equal?(append(make-list(- 1 y)#\a)(make-list y #\b))(cdr x)))(/(length x)2)))

Expects input in the form of a list of characters. If you really need to put it in as a raw string, that adds 21 extra characters (for 112 bytes):

(λ(x)((λ(y)(equal?(append(make-list(- 1 y)#\a)(make-list y #\b))(cdr(string->list x))))(/(string-length x)2)))

An even longer (102 bytes with list input) way, but I think it's creative so I'm leaving it here:

(λ(x)(and(eqv?(/(length x)2)(length(member #\b x)))(eqv?(length(remove-duplicates(member #\b x)))1)))

Explanation to follow.

Steven H.

Posted 2016-07-20T19:12:01.463

Reputation: 2 841

1

Actually, 14 bytes

"[]""ab"(t≡#ÆY

This uses the same strategy as xnor's solution for the first part: transform the input into a nested iterable.

Try it online!

Explanation:

"[]""ab"(t≡#ÆY
"[]""ab"(t      translate "a" -> "[", "b" -> "]"
          ≡     eval (since this is evaluating a literal, it still works in the online interpreter) - leaves a list if the string is valid, else a string
           #    listify (does nothing to a list, makes a list of characters for a string)
            Æ   filter strings (take all string elements in the list - so an empty list if there are none)
             Y  boolean negate (an empty list is falsey and a non-empty list is truthy, so negation gets the correct value)

Mego

Posted 2016-07-20T19:12:01.463

Reputation: 32 998

1

C#, 78 67 bytes

bool f(string s)=>Regex.IsMatch(s,"^(?'o'a)+(?'-o'b)+(?(o)(?!))$");

This implementation uses .NET Regex's "Balancing Group Definitions" to match the same number of 'a' and 'b' characters while ensuring that the input isn't an empty string by using the + quantifier.

Dion Williams

Posted 2016-07-20T19:12:01.463

Reputation: 11

1

Python, 101 bytes

def q(s):  
 a=len(s)/2  
 for x in range(a):  
  if s[x]!='a' or s[a+x]!='b' or a*2!=len(s):a=0
return a

Not the most efficient, had some trouble with 0 being even. Could probably get it lower with python tricks.
Returns 0 if false, a positive integer if true. (which will be half len(s))

greyShift

Posted 2016-07-20T19:12:01.463

Reputation: 221

1

k (21 bytes)

Can probably be shorter

{|/0,(=).(#:'=x)"ab"}

Example

k){|/0,(=).(#:'=x)"ab"}""
0b
k){|/0,(=).(#:'=x)"ab"}"ab"
1b
k){|/0,(=).(#:'=x)"ab"}"aab"
0b

skeevey

Posted 2016-07-20T19:12:01.463

Reputation: 4 139

Gives the wrong answer for "abba" – geocar – 2016-07-31T13:02:51.913

1

PHP bounty version, 31 bytes

for PHP 4.1, call php-cgi -f <scriptname> s=<argument> (or in browser with ?s=<argument>)

for current PHP, use $_GET[s] instead of $s


31 bytes

<?eval(strtr("do$s;",ab,'{}'));

unexpected ';' for valid, unexpected end of file or unexpected '}' for invalid

<?eval(strtr("1|$s;",ab,'[]'));

ok for valid, unexpected ';' or unexpected ']' for invalid

26 bytes

if empty input was undefined or valid:

<?eval(strtr($s,ab,'{}'));

29 bytes, if empty input was undefined or valid:

<?eval(strtr("$s;",ab,'[]'));

Abusing other control structures:

32 bytes

<?eval(strtr("$c=$s;",ab,'[]'));

ok for valid, Parse error for invalid: unexpected ';', unexpected ']' or Cannot use [] for reading (for abab)

33 bytes

<?eval(strtr("1 or$s;",ab,'[]'));

same as 1|

<?eval(strtr("if(0)$s",ab,'{}'));

ok for valid, unexpected end of file or unexpected '}' for invalid input

35 bytes:

<?eval(strtr("for(;;)$s",ab,'{}'));

infinite loop for valid (use for(;0;) to make finite), same as if for invalid

36 bytes

<?eval(strtr("while(0)$s",ab,'{}'));

same as if

39 bytes

<?eval(strtr("function()$s;",ab,'{}'));

unexpected ';' for empty, same as if for other input

Titus

Posted 2016-07-20T19:12:01.463

Reputation: 13 814

1

Matlab, 67 chars

s=input('');l=num2str(length(s)/2);regexp(s,['^a{',l,'}b{',l,'}$'])

The regular expression searches for exactly half the input's length in as consecutively at the beginning of the input string, followed by exactly half of the input's length in bs consecutively right up to the end of the input string. It returns [] on a non-even-length input, empty strings, and non-Language-L strings and only returns 1 on strings that are part of Language L.

sintax

Posted 2016-07-20T19:12:01.463

Reputation: 291

1

TI-Basic, 35 bytes

Zero is True; anything else is False.

Input Str1
1+.5length(Str1
inString(Str1,"a",Ans) or Ans≠inString(Str1,"b

Explanation

Input Str1                 Get string into Str1
1+.5length(Str1            Get number that is one more than half. For example, 8 gives 5.
inString(Str1,"a",Ans)     Yields zero if there is no instances of a in the second half
                               (using the number we just calculated as the start point for the search)
 or                        Both conditions need to be zero in order to output zero
Ans≠inString(Str1,"b       Yields zero if the first instance of b is the number we calculated earlier

Timtech

Posted 2016-07-20T19:12:01.463

Reputation: 12 038

I think you might be confused... parentheses don't have to be closed in TI-Basic. Thanks for the concern, though. – Timtech – 2016-07-28T16:38:24.900

You're not using TI-Basic's notion of truthy/falsy here. How is that allowed? – Jakob – 2017-08-29T19:24:40.310

1I answered this a while ago, and it seems that we could specify which outputs indicated true or false. But, in accordance with your suggestion you could add not( to the beginning of the last line. – Timtech – 2017-08-29T23:08:17.510

1

Ruby, 42 bytes

This is a simple solution, but unfortunately longer than many of the other Ruby solutions.

->s{s=~/^a+b+$/&&s.count(?a)==s.count(?b)}

Ungolfed:

def f(s)
  if s =~ /^a+b+$/ && s.count(?a) == s.count(?b)
    return true
  else
    return nil
  end
end

Sherlock9

Posted 2016-07-20T19:12:01.463

Reputation: 11 664

1

><>, 52 bytes

Prints zero if input is false, n otherwise (the number of a's and b's).

0&i:0(?v10.
&v?(2l~<0rv!?='a'r0!?='b'&+1
 >l0=&*n;n<

Try it online!

owacoder

Posted 2016-07-20T19:12:01.463

Reputation: 1 556

1

K, 21 Bytes

0b is false and 1b is true;

    f:{(~).{+/x=y}[x]'"ab"}
    tests:("ab";"abbbb";"bbbbaa";"aabbababba";"bb";"aabaaabaaa";"aabbb";"aaabbaaabb";"ba";"bbbabbaabb")
    f'tests
    1001000010b

Chromozorz

Posted 2016-07-20T19:12:01.463

Reputation: 338

Edit - from seeing another answer I've shortened it down to 17 Bytes; {(~).(#:'=x)"ab"} – Chromozorz – 2016-07-30T22:44:13.190

1

Pyth, 7 bytes

.AanV_S

Try it online

How it works

      SQ     sorted input
     _       reverse
   nV   Q    vectorized not-equal with input
  a      Q   append input
.A           test whether all elements are truthy

Anders Kaseorg

Posted 2016-07-20T19:12:01.463

Reputation: 29 242

1

K, 10 bytes

~/1_'-':'=

Note this is a function, so it needs to be called:

  ~/1_'-':'="aaaaaabbbbbb"
1
  ~/1_'-':'="aba"
0

= groups its arguments, so ="aaaaaabbbbbb" produces "ab"!(0 1 2 3 4 5;6 7 8 9 10 11) and ="aba" returns "ab"!(0 2;,1)

-':' is minus eachprior each. -': is a good way to find out if a series is increasing (or decreasing). -':'="aaaaaabbbbbb" gives us "ab"!(0 1 1 1 1 1;6 1 1 1 1 1) and -':'="aba" gives us "ab"!(0 2;,1)

1_' is one drop each which pops the first element off each list.

~/ is match over.

geocar

Posted 2016-07-20T19:12:01.463

Reputation: 214

1

Perl 6, 49 bytes

grammar {token TOP{a<TOP>?b}}.parse(get).Bool.say

My entry for dmckee’s bounty. Checks the string using Perl 6’s parsing facilities.

Lynn

Posted 2016-07-20T19:12:01.463

Reputation: 55 648

1

Bash, 50 bytes

l=$[${#1}/2]
[[ $1 =~ a{$l}b{$l}$ ]]&&echo $[$l>0]

It always returns 1 in case the statement is true, otherwise it doesn't return something except if the input is the empty string '', then it returns 0.

Example:

$ bash script 'aa'
$ bash script 'ab'
1
$ bash script 'aabb'
1
$ bash script ''
0

It can be a bit shorter (46 bytes) if it returns $l in case of success.

l=$[${#1}/2]
[[ $1 =~ a{$l}b{$l}$ ]]&&echo $l 

In case of success it always returns a value > 0, if the input is the empty string it returns 0 and otherwise it doesn't return anything.

Examples:

$ bash t.sh 'aa'
$ bash t.sh 'ab'
1
$ bash t.sh 'aabb'
2
$ bash t.sh ''
0

Master_ex

Posted 2016-07-20T19:12:01.463

Reputation: 526

1

Thue, 39 bytes

$::=:::
ab::=x
axb::=x
-x-::=~1
::=
-$-

Outputs a "1" for true and nothing for false.

MegaTom

Posted 2016-07-20T19:12:01.463

Reputation: 3 787

1

R, 79 bytes

a=function(s){all(nchar(strsplit(s,"ab")[[1]])==nchar(s)/2-1)&&!grepl("ba",s)}

Tests if when split on "ab" all substrings are the same precalculated length, and it tests if the pattern "ba" occurs anywhere.

user5957401

Posted 2016-07-20T19:12:01.463

Reputation: 699

0

Clojure, 52 bytes

#(=(seq %)(mapcat(fn[c](repeat(/(count %)2)c))"ab"))

Instead of parsing the string this one generates a sequence how it should look like :) (seq "") is nil but the mapcat produces an empty list, so (f "") is false.

NikoNyrh

Posted 2016-07-20T19:12:01.463

Reputation: 2 361

0

///, 41 bytes + input [47 with empty input acceptance]

/'/"|//|a/a|//a|b/|//"|"///a///b///"|//'(input)'
A     B      C      D     E   F   G

NB: second line is used in explanation, not part of the code

There's no /// submission yet?! Outputs | for true, (empty output) for false.

Gives a false positive on the empty input, add /''/|/ at the start for +6 bytes if needed.

Example parsings (which hopefully should be illustrative):

  • 'aabb' A "|aabb"| B "a|abb"| B "aa|bb"| C "a|b"| C "|"| D |
  • 'abab' A "|abab"| B "a|bab"| C "|ab"| E "|b"| F "|"| G "| G

Try it online!

boboquack

Posted 2016-07-20T19:12:01.463

Reputation: 2 017

0

Lua, 37 bytes

Works with Lua 5.1, Lua 5.2, and Lua 5.3.

os.exit((...):match"^%bab$":find"ba")

Try it online!

Exit status zero for truthy, non-zero for falsey. (Assumes the default success exit code is zero.)

The match call uses %b to check if the string is a "balanced" (in the sense of parentheses) string of a and b. In particular, this means the numbers of a and b is the same and the string is non-empty. If this fails, it will return nil, and the call to find will throw, giving a falsey exit status. Otherwise, it will return the whole string again.

If the call to find fails, then all the a preceed all the b and the string is valid. find will return nil and os.exit will give a default exit status (zero). If the call to find succeeds, it will return the index where it found ba which will be nonzero.

tehtmi

Posted 2016-07-20T19:12:01.463

Reputation: 446

0

///, 38 + input bytes

input goes between the n and the x at the end.

/nx///ba/0//ab///a/0//b/0//n0/0//x//nx

A lot of this code is getting the output format correct. Outputs a single n if it it truthy, and a string consisting of 0s if it it falsy.

///, 11 + input bytes

/ba/0//ab//

Input goes at the end. Output the empty string if it is falsy, or a string consisting of a, b, and 0 if it is truthy.

pppery

Posted 2016-07-20T19:12:01.463

Reputation: 3 987

0

Batch, 50 bytes

@set x=%1
@if %x:b=%%x%%x:a=% neq %x:b=a%%x:a=b% *

Output nothing and return 0 for true and something returning 9009 for false

If %x% contain a as and b bs, %x:b=%%x%%x:a=% contains 2a as and 2b bs, while %x:b=a%%x:a=b% contain a+b as and a+b bs, so if they're equal, a=b. Meanwhile, %x% in %x:b=%%x%%x:a=% occupies the middle part, which in %x:b=a%%x:a=b% is a as and a bs, so they can be and will be equal if it matchs {a}^n{b}^n.

For empty string, the IF statement fails to parse and echo about that.

l4m2

Posted 2016-07-20T19:12:01.463

Reputation: 5 985

0

Python 2.7, 37 bytes

lambda s:s.count('a')==s.count('b')>0

Khalil

Posted 2016-07-20T19:12:01.463

Reputation: 49

0

SNOBOL4 (CSNOBOL4), 81 bytes

	N =INPUT	:F(END)
	Y =SIZE(N) / 2
	OUTPUT =IDENT(N,DUPL('a',Y) DUPL('b',Y)) 1
END

Try it online!

Generate a string of a..b.. with the right size and test if the strings are IDENTical. Prints 1 for truthy and nothing for falsy.

Giuseppe

Posted 2016-07-20T19:12:01.463

Reputation: 21 077

0

Gol><>, 26 bytes

&TiE!tlF:`a=Q&P&~{|}|l&-zh

Wow, five minutes and it is already smaller, 4 bytes knocked off!

Try it online!

Older version, 30 bytes

&TiE!tlF:`a=:Q&P&~|zQ}||l&-0=h

Wow! This was going to be alot larger than this, but I realized that I can combine 2 checks in one towards the end. This can be golfed alot more, but I will be working on that soon!!!

&TiE!t                           //Get all of the characters
      lF                         //Loop through the entire stack
        :`a=:                    //Check if it is equal to a
             Q&P&~|              //If so, increment a variable and delete that character
                   zQ}|          //Otherwise, continue
                       |         //end of loop
                        l&-0=h   //the remaining b# is subtracted from the # of a, if it is zero it will output 1, otherwise 0

Try it online!

KrystosTheOverlord

Posted 2016-07-20T19:12:01.463

Reputation: 681

abab should be falsey. I know the title is misleading, but truthy cases are only as followed by only bs. e.g. aaabbb is true, ababab is false – Jo King – 2019-03-20T23:41:15.477

@JoKing Well then, I will fix that, it should be an easy fix where I do the deleting process, delete the previous letter rather than itself, and then check if the previous and itself are the same. Thanks for pointing that out, I'll fix it as soon as I have time – KrystosTheOverlord – 2019-03-21T00:12:03.393

0

Perl 6 (33 bytes)

{?/^(a+)(b+)$/&&$0.ords==$1.ords}

bb94

Posted 2016-07-20T19:12:01.463

Reputation: 1 831

Fixed the first problem. And I'm sure chrs works, because == coerces its arguments into numbers before performing the comparison. – bb94 – 2019-03-21T02:07:11.867

You're right; I was thinking of ords. – bb94 – 2019-03-21T02:13:18.410

130 bytes – Jo King – 2019-03-21T02:22:12.363

0

APL(NARS), 23 chars, 46 bytes

{⍵≡'':0⋄⍵≡'ab'/⍨⌈2÷⍨≢⍵}

test:

  f←{⍵≡'':0⋄⍵≡'ab'/⍨⌈2÷⍨≢⍵}
  f ''
0
  f¨(,'a')(,'b')('aa')('ba')
0 0 0 0 
  f¨('ab')('aabb')('aaabbb')('aaaabbbb')
1 1 1 1 
  f¨('abb')('aabbb')('aaaabbb')('aaaaabbbb')
0 0 0 0 

RosLuP

Posted 2016-07-20T19:12:01.463

Reputation: 3 036

0

C# (Visual C# Interactive Compiler), 54 bytes

x=>x!=""&!x.OrderBy(y=>-y).Where((y,i)=>y==x[i]).Any()

Try it online!

Port of Dennis's MATL solution. Below is a 48 byte version that matches the empty string.

x=>!x.OrderBy(y=>-y).Where((y,i)=>y==x[i]).Any()

Try it online!

dana

Posted 2016-07-20T19:12:01.463

Reputation: 2 541

0

Python 2, 42 bytes

f=lambda s:s=='ab'or s<s[-1:]>0<f(s[1:-1])

Try it online!

Chas Brown

Posted 2016-07-20T19:12:01.463

Reputation: 8 959

0

Stax, 8 bytes

é«<òαøòâ

Run and debug it

It compares the input with "ab" having its characters repeated inputLength / 2 times.

recursive

Posted 2016-07-20T19:12:01.463

Reputation: 8 616

0

C, 85 bytes

n,d;f(char*v){while(*v)if(*v++&1){if(n++,d)return 0;}else d?n--:(n--,d=1);return!n;}

Pretty long. Seems to handle all edge cases correctly.

Ungolfed:

n, d;
f (char *v) {
    while (*v)
        if (*v++ & 1) {
            if(n++, d)
                return 0;
        } else
            d ? n-- : (n-- , d = 1);
    return !n;
}

qookie

Posted 2016-07-20T19:12:01.463

Reputation: 81

0

brainfuck and bfasm, 995 and 119 bytes

Quite easy to outgolf.

Generated using following assembly code:

mov r4,.a
lbl 1
in_ r1
jz_ r1,3
eq_ r1,r4
jnz r1,2
inc r3
dec r2
lbl 2
inc r2
jmp 1
lbl 3
eq_ r2,r3
out r2

And then optimized by hand.

+>+[<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>>--[----->+<]>-----<<<<<]>+<<+<<[>>->+<<<-]>>>[<<<+>>>-]<[->+<<[>>>-<<+<-]>[<+>-]>>[<->[-]]<[<<<+>>>-]<]<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>,>>>>+++<<<<<<+>>[<<[-]<+>>>-]<<<[>>>+<<<-]>[<<<[-]>[-]>>>>>>>>[<<<<<<<<+>+>>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>[-]]>>>>>>[-]<<<<<<]<<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>[<<+>>-]+>>>[<<<<<-<+>>>>>>-]<<<<<<[>>>>>>+<<<<<<-]>[>>-<<[-]]>>>>>>++<<<<[<<<+>+>>-]<<<[>>>+<<<-]>[<<<[-]>[-]>>>>>>>>[<<<<<<<<+>+>>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>[-]]>>>>>>[-]<<<<<<]<<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>>+<-<<<]>++<<+<<[>>->+<<<-]>>>[<<<+>>>-]<[->+<<[>>>-<<+<-]>[<+>-]>>[<->[-]]<[<<<+>>>-]<]>>[-]<<<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>+>>>+<<<<<<<<<[-]>[-]>>>>>>>>[<<<<<<<<+>+>>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>>>>>>>[-]<<<<<<]>+++<<+<<[>>->+<<<-]>>>[<<<+>>>-]<[->+<<[>>>-<<+<-]>[<+>-]>>[<->[-]]<[<<<+>>>-]<]>>[-]<<<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>[<<<+>>>-]+>[<<<<-<+>>>>>-]<<<<<[>>>>>+<<<<<-]>[>>>-<<<[-]]>>>.<<<]<<<[>>+>+<<<-]>>[<<+>>-]>[[-]<<<[-]>[-]>>]<<]

Try it online!

Krzysztof Szewczyk

Posted 2016-07-20T19:12:01.463

Reputation: 3 819

0

C# .NET 135 bytes

public class P{public static void Main(string[]a){System.Console.Write(a[0]!=""&&a[0].Split('a').Length-1==a[0].Split('b').Length-1);}}

Try online

canttalkjustcode

Posted 2016-07-20T19:12:01.463

Reputation: 131

0

GolfScript, 20 bytes

.,2//zip{"ab"=}%{&}*

Try it online!

user85052

Posted 2016-07-20T19:12:01.463

Reputation:

0

Unix TMG, 64 bytes

p:<a>f((<b>))parse((any(!<<>>)|={<1>}));f:proc(x)<a>f((<b>x))|x;

Works by recursive-descent parsing. It outputs "1" for match, nothing otherwise.

Expanded:

prog:   <a> recurs(( <b> )) parse(( any(!<<>>) | = { <1> } ));
recurs: proc(x) <a> recurs(( <b> x )) 
      | x;

The solution is based on the one in McIlroy's Tmg Manual (1972) for anbncn.

Andriy Makukha

Posted 2016-07-20T19:12:01.463

Reputation: 404

0

Keg, 14 bytes

:⑴½ℤ:a⅍*$b⅍*+=

Try it online!

Same approach as the stax answer.

Lyxal

Posted 2016-07-20T19:12:01.463

Reputation: 5 253