[Question]
  [
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:
$$\large{L=\{a^n b^n:n\in\mathbb{Z}^+\}}$$
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.](https://codegolf.meta.stackexchange.com/questions/2190/interpretation-of-truthy-falsey)
* Standard code golf rules apply.
This is a [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"). 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>
```
  
[Answer]
## Python 3, 32 bytes
```
eval(input().translate(")("*50))
```
[Try it online!](https://tio.run/##ZVFNbusgEN5zihEbzEtqJarexlaWPUVaWfBCWiQXEEyapgfoumfsRVJmcLp5yGL@vu@bGZwu@BLD/dW/ppgRfFyXS1m3aPZWHNwRJh/SCTs9wPMcrZkBXcERssNTDhyIabInP6MPZZp6hsNu4Y0QkwudJFzp00Wu5Vnq/pw9ui5LKa/uzczd0qPHbEKZTa1J3ck/fzdaXytovx3utk96hDpenwy@1C7FZew2a1Cq5j92G3GMGeoOgUEFDz4MAurxR/gYbsl4wqW5egxK3wC4r/q7HeUGoOlxTx25TKNTZgRXjdqols2XJk8n0b5Te7dpWraV@rfeRvh91z67OZpDlxrCvf9zCeGBjY8BTAGX89D6bdV4G74mb8NLtcKVkgMoWNV/kXJXi7r6vNbIuv@t7KgO359fIImGFMr2fNurscIYS1e92ZBtDnuL23wrhBGUEbZ@XCK6MDUkFcuVarncqCxNKIIYvojQGEwhDpEIYlmGdZpQU7I/ "Python 3 – Try It Online")
[Outputs via exit code](https://codegolf.meta.stackexchange.com/a/5330/20260): 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.
[Try it online!](https://tio.run/##ZVBBjtswDLzrFYR6kNWkRrynwoaPfUVaGNJG2RXgSoJEd5t9QM99Yz@SkpLTSwVDpGY4Q9Lphq8xPN0/PMeLDy/zhlfhv6eYEXw8lls50ktc3BUWH9KGnR7hZY3WrICu4ATZ4ZYDuB9m7RjRYlns5lf0oSxLX0Uw7@oJYnKhk1xY@nSTR/kmdf@WPbouSynv1Wfv1GM2oayGOKk7@XF4@qz1narOw/hp@KYnoPn6ZPCV2hSXsTsdQSnC3@eTuMYMtESoRQVpu1EAHX@F9/EBxg337uprUPpRgGfyn2fGRuDx8cwdK82zE6KkOuCB7gkcP0@qsfnW2vBJvPjSfuey7GtL/Y9voxDfZ7dGc@lS49zPZ5cQvtTgYwBTwOU8tk6Dmh7jE7iPX6c6AI2rKGSXckekZogXm6rvf0s75uHPr98gWVYdZPuBw91YYYzli@4aOLakZnvaciuEEYwIS1@lWC4MPdnFVoZipZu0WnMVl5h6saApqoQ1LOISW22qTzNqTvYv "Python 2 – Try It Online") (Python 2, 33 bytes)
[Answer]
# [MATL](https://github.com/lmendo/MATL), ~~5~~ 4 bytes
```
tSP-
```
Prints a non-empty array of **1**s if the string belongs to **L**, and an empty array or an array with **0**s (both falsy) otherwise.
*Thanks to @LuisMendo for golfing off 1 byte!*
[Try it online!](http://matl.tryitonline.net/#code=dFNQLQ&input=J2FhYmIn)
### 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.
```
[Answer]
## [Retina](https://github.com/m-ender/retina), 12 bytes
*Credits to FryAmTheEggman who found this solution independently.*
```
+`a;?b
;
^;$
```
Prints `1` for valid input and `0` otherwise.
[Try it online!](http://retina.tryitonline.net/#code=JShHYAorYGE7P2IKOwpeOyQ&input=YWIKYWFiYgphYWFhYmJiYgphYWFhYWFhYmJiYmJiYgoKYQpiCmJhCmFiYWIKYWFiCmFiYgphYWFhYmJi) (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 `a`s and the `b`s 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 `a`s and the `b`s 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 `a`s and `b`s) because the first iteration will find multiple `ab`s 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`.)
[Answer]
## 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](https://codegolf.stackexchange.com/a/83103/20260) 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.
[Answer]
## [Grime](http://github.com/iatorm/grime), 12 bytes
```
A=\aA?\b
e`A
```
[Try it online!](http://grime.tryitonline.net/#code=QT1cYUE_XGIKZWBB&input=YWFhYWJiYmI)
## 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`.
[Answer]
# [Brachylog](https://github.com/JCumin/Brachylog), ~~23~~ 19 bytes
```
@2L,?lye:"ab"rz:jaL
```
[Try it online!](http://brachylog.tryitonline.net/#code=QDJMLD9seWU6ImFiInJ6OmphTA&input=ImFhYWFhYWFiYmJiYmJiIg)
### 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
```
[Answer]
# 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.
[Answer]
# J, ~~17~~ 15 bytes
*-2 bytes thanks to [Jonah](https://codegolf.stackexchange.com/users/15469/jonah)!*
```
#<.2&#-:'ab'#~#
```
This works correctly for giving falsey for the empty string. Error is falsey.
Other versions:
```
<e.'ab'<@#"{~#\       NB. alternate 15 bytes, thanks to Jonah
#<.(-:'ab'#~-:@#)
NB. the following do not handle the empty string correctly
-:'ab'#~-:@#
2&#-:'ab'#~#          NB. thanks to miles
```
## Proof and explanation
*Outdated, but applicable to the old 17 byte version.*
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](http://www.jsoftware.com/help/learning/09.htm), 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.
[Answer]
# [05AB1E](http://github.com/Adriandmen/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!](http://05ab1e.tryitonline.net/#code=Lk17SsK5w5RR&input=YWFhYWJiYmI).
[Answer]
# [Jelly](http://github.com/DennisMitchell/jelly), 6 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
Ṣ=Ṛ¬Pȧ
```
Prints the string itself if it belongs to **L** or is empty, and **0** otherwise.
[Try it online!](http://jelly.tryitonline.net/#code=4bmiPeG5msKsUMin&input=&args=YWFiYg) or [verify all test cases](http://jelly.tryitonline.net/#code=4bmiPeG5msKsUMinCsOH4oKsauKBtw&input=&args=ImFiIiwgImFhYmIiLCAiYWFhYmJiIiwgImFhYWFiYmJiIiwgImFhYWFhYmJiYmIiLCAiYWFhYWFhYmJiYmJiIiwgIiIsICJhIiwgImIiLCAiYWEiLCAiYmEiLCAiYmIiLCAiYWFhIiwgImFhYiIsICJhYmEiLCAiYWJiIiwgImJhYSIsICJiYWIiLCAiYmJhIiwgImJiYiIsICJhYWFhIiwgImFhYWIiLCAiYWFiYSIsICJhYmFhIiwgImFiYWIiLCAiYWJiYSIsICJhYmJiIiwgImJhYWEiLCAiYmFhYiIsICJiYWJhIiwgImJhYmIiLCAiYmJhYSIsICJiYmFiIiwgImJiYmEiLCAiYmJiYiI).
### 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!](http://jelly.tryitonline.net/#code=4bmibuG5msim&input=&args=) or [verify all test cases](http://jelly.tryitonline.net/#code=4bmibuG5msimCsOH4oKsRw&input=&args=ImFiIiwgImFhYmIiLCAiYWFhYmJiIiwgImFhYWFiYmJiIiwgImFhYWFhYmJiYmIiLCAiYWFhYWFhYmJiYmJiIiwgIiIsICJhIiwgImIiLCAiYWEiLCAiYmEiLCAiYmIiLCAiYWFhIiwgImFhYiIsICJhYmEiLCAiYWJiIiwgImJhYSIsICJiYWIiLCAiYmJhIiwgImJiYiIsICJhYWFhIiwgImFhYWIiLCAiYWFiYSIsICJhYmFhIiwgImFiYWIiLCAiYWJiYSIsICJhYmJiIiwgImJhYWEiLCAiYmFhYiIsICJiYWJhIiwgImJhYmIiLCAiYmJhYSIsICJiYmFiIiwgImJiYmEiLCAiYmJiYiI).
### 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.
```
[Answer]
# 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(''))
```
[Answer]
## Perl 5.10, ~~35~~ 17 bytes (with *-n* flag)
```
say/^(a(?1)?b)$/
```
Ensures that the string starts with `a`s and then recurses on `b`s. It matches only if both lengths are equal.
Thanks to [Martin Ender](https://codegolf.stackexchange.com/users/8478/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!](http://ideone.com/jSHlcB)
[Answer]
## 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!](http://ideone.com/10U9t6)
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), ~~7~~ ~~6~~ ~~5~~ 4 bytes
```
I÷<g
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiZiIsIknDtzxnIiwiIiwiXCJhYlwiXG5cImFhYmJcIlxuXCJhYWFiYmJcIlxuXCJhYWFhYmJiYlwiXG5cImFhYWFhYmJiYmJcIlxuXCJhYWFhYWFiYmJiYmJcIlxuXCJcIlxuXCJhXCJcblwiYlwiXG5cImFhXCJcblwiYmFcIlxuXCJiYlwiXG5cImFhYVwiXG5cImFhYlwiXG5cImFiYVwiXG5cImFiYlwiXG5cImJhYVwiXG5cImJhYlwiXG5cImJiYVwiXG5cImJiYlwiXG5cImFhYWFcIlxuXCJhYWFiXCJcblwiYWFiYVwiXG5cImFiYWFcIlxuXCJhYmFiXCJcblwiYWJiYVwiXG5cImFiYmJcIlxuXCJiYWFhXCJcblwiYmFhYlwiXG5cImJhYmFcIlxuXCJiYWJiXCJcblwiYmJhYVwiXG5cImJiYWJcIlxuXCJiYmJhXCJcblwiYmJiYlwiIl0=)  
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiIiwiScO3PGciLCIiLCJbXCJhXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXVxuW1wiYVwiXVxuW1wiYlwiXVxuW1wiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiLFwiYlwiXSJd) - without the `f` header
Takes a list of characters as input. Outputs `1` for true for inputs in \$\{a^n b^n:n∈\mathbb{Z}^+\}\$, and empty string or `0` for false otherwise. This matches Vyxal's truthy/falsey semantics, which can be confirmed by putting `ḃ` (Boolify) in the Footer.
```
I   # Into Two Pieces - Splits a list into two halves and wraps them in a list.
    # If the input is odd in length, the left side gets 1 more character.
÷   # Item Split - Unwraps the list created above. Required so that the next
    # operation can compare the two halves.
<   # Less Than (vectorized) - Are items in the left half list less than the
    # corresponding items in the right half list? Puts 1 where yes, 0 where no.
    # The resulting list takes the size of whichever list was longer. For items
    # at the end of that list with no corresponding item in the other list, it
    # puts 0 if that position is empty in the right list, and 1 if it's empty in
    # the left list (which can never happen in this program).
g   # Minimum
```
---
Determining membership in \$\{a^n b^n:n∈\mathbb{Z}^0\}\$ can also be done in 4 bytes:
```
I÷<A
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiZiIsIknDtzxBIiwiIiwiXCJhYlwiXG5cImFhYmJcIlxuXCJhYWFiYmJcIlxuXCJhYWFhYmJiYlwiXG5cImFhYWFhYmJiYmJcIlxuXCJhYWFhYWFiYmJiYmJcIlxuXCJcIlxuXCJhXCJcblwiYlwiXG5cImFhXCJcblwiYmFcIlxuXCJiYlwiXG5cImFhYVwiXG5cImFhYlwiXG5cImFiYVwiXG5cImFiYlwiXG5cImJhYVwiXG5cImJhYlwiXG5cImJiYVwiXG5cImJiYlwiXG5cImFhYWFcIlxuXCJhYWFiXCJcblwiYWFiYVwiXG5cImFiYWFcIlxuXCJhYmFiXCJcblwiYWJiYVwiXG5cImFiYmJcIlxuXCJiYWFhXCJcblwiYmFhYlwiXG5cImJhYmFcIlxuXCJiYWJiXCJcblwiYmJhYVwiXG5cImJiYWJcIlxuXCJiYmJhXCJcblwiYmJiYlwiIl0=)  
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiIiwiScO3PEEiLCIiLCJbXCJhXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXVxuW1wiYVwiXVxuW1wiYlwiXVxuW1wiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiLFwiYlwiXSJd) - without the `f` header
Takes a list of characters as input. Outputs `1` for true and `0` for false. Only the last element of the program is different:
```
A   # Check if all items in a list are truthy (returns truthy for an empty list)
```
# [Vyxal](https://github.com/Vyxal/Vyxal), ~~6~~ ~~5~~ 4 bytes
```
sṘ꘍g
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiZjoiLCJz4bmY6piNZyIsIiIsIlwiYWJcIlxuXCJhYWJiXCJcblwiYWFhYmJiXCJcblwiYWFhYWJiYmJcIlxuXCJhYWFhYWJiYmJiXCJcblwiYWFhYWFhYmJiYmJiXCJcblwiXCJcblwiYVwiXG5cImJcIlxuXCJhYVwiXG5cImJhXCJcblwiYmJcIlxuXCJhYWFcIlxuXCJhYWJcIlxuXCJhYmFcIlxuXCJhYmJcIlxuXCJiYWFcIlxuXCJiYWJcIlxuXCJiYmFcIlxuXCJiYmJcIlxuXCJhYWFhXCJcblwiYWFhYlwiXG5cImFhYmFcIlxuXCJhYmFhXCJcblwiYWJhYlwiXG5cImFiYmFcIlxuXCJhYmJiXCJcblwiYmFhYVwiXG5cImJhYWJcIlxuXCJiYWJhXCJcblwiYmFiYlwiXG5cImJiYWFcIlxuXCJiYmFiXCJcblwiYmJiYVwiXG5cImJiYmJcIiJd)  
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiIiwic+G5mOqYjWciLCIiLCJbXCJhXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXVxuW1wiYVwiXVxuW1wiYlwiXVxuW1wiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiLFwiYlwiXSJd) - without the `f:` header
Takes a list of characters as input. Outputs `1` for true for inputs in \$\{a^n b^n:n∈\mathbb{Z}^+\}\$, and empty string or `0` for false otherwise.
This is a port of [Dennis's MATL answer](https://codegolf.stackexchange.com/a/86037/17216), with an algorithm also used by many subsequent answers.
```
s   # Pushes a copy of the input, sorted.
Ṙ   # Reverses the sorted copy.
꘍   # Levenshtein distance (vectorized) - Used here to compare corresponding
    # single-character strings between two lists, so it's effectively a vectorized
    # Not Equals, giving 1 for unequal and 0 for equal. This works around the fact
    # that Vyxal has no vectorizing Not Equals operator (even though it does have
    # vectorizing versions of all the other basic comparison operators). For input
    # in L, this will yield a non-empty list of all 1s. For an empty input it will
    # yield an empty list. For all other inputs it yields a list of both 1s and 0s.
g   # Minimum
```
To take a string as input, this becomes `f:sṘ꘍g` or alternatively `fṘḂs꘍g` (6 bytes). It is, however, possible to do this with the sort-and-reverse algorithm in 5 bytes (see `AḂs꘍↓` below).
---
Determining membership in \$\{a^n b^n:n∈\mathbb{Z}^0\}\$ can also be done in 4 bytes using this algorithm:
```
sṘ꘍A
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiZjoiLCJz4bmY6piNQSIsIiIsIlwiYWJcIlxuXCJhYWJiXCJcblwiYWFhYmJiXCJcblwiYWFhYWJiYmJcIlxuXCJhYWFhYWJiYmJiXCJcblwiYWFhYWFhYmJiYmJiXCJcblwiXCJcblwiYVwiXG5cImJcIlxuXCJhYVwiXG5cImJhXCJcblwiYmJcIlxuXCJhYWFcIlxuXCJhYWJcIlxuXCJhYmFcIlxuXCJhYmJcIlxuXCJiYWFcIlxuXCJiYWJcIlxuXCJiYmFcIlxuXCJiYmJcIlxuXCJhYWFhXCJcblwiYWFhYlwiXG5cImFhYmFcIlxuXCJhYmFhXCJcblwiYWJhYlwiXG5cImFiYmFcIlxuXCJhYmJiXCJcblwiYmFhYVwiXG5cImJhYWJcIlxuXCJiYWJhXCJcblwiYmFiYlwiXG5cImJiYWFcIlxuXCJiYmFiXCJcblwiYmJiYVwiXG5cImJiYmJcIiJd)  
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiIiwic+G5mOqYjUEiLCIiLCJbXCJhXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJhXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCIsXCJiXCJdXG5bXVxuW1wiYVwiXVxuW1wiYlwiXVxuW1wiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYVwiLFwiYlwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYVwiLFwiYlwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYVwiLFwiYlwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiLFwiYVwiXVxuW1wiYlwiLFwiYlwiLFwiYlwiLFwiYlwiXSJd) - without the `f:` header
Takes a list of characters as input. Outputs `1` for true and `0` for false.
To take a string as input, this becomes `f:sṘ꘍A` or alternatively `fṘḂs꘍A` (6 bytes). It is, however, possible to do this with the sort-and-reverse algorithm in 5 bytes (see `AḂs꘍A` below).
# [Vyxal](https://github.com/Vyxal/Vyxal), 5 bytes
```
fI÷<g
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiIiwiZknDtzxnIiwiIiwiXCJhYlwiXG5cImFhYmJcIlxuXCJhYWFiYmJcIlxuXCJhYWFhYmJiYlwiXG5cImFhYWFhYmJiYmJcIlxuXCJhYWFhYWFiYmJiYmJcIlxuXCJcIlxuXCJhXCJcblwiYlwiXG5cImFhXCJcblwiYmFcIlxuXCJiYlwiXG5cImFhYVwiXG5cImFhYlwiXG5cImFiYVwiXG5cImFiYlwiXG5cImJhYVwiXG5cImJhYlwiXG5cImJiYVwiXG5cImJiYlwiXG5cImFhYWFcIlxuXCJhYWFiXCJcblwiYWFiYVwiXG5cImFiYWFcIlxuXCJhYmFiXCJcblwiYWJiYVwiXG5cImFiYmJcIlxuXCJiYWFhXCJcblwiYmFhYlwiXG5cImJhYmFcIlxuXCJiYWJiXCJcblwiYmJhYVwiXG5cImJiYWJcIlxuXCJiYmJhXCJcblwiYmJiYlwiIl0=)
Takes a string as input. Outputs `1` for true for inputs in \$\{a^n b^n:n∈\mathbb{Z}^+\}\$, and empty string or `0` for false otherwise. This is just one of the above 4 byte programs with `f` inserted at the beginning.
---
Determining membership in \$\{a^n b^n:n∈\mathbb{Z}^0\}\$ can also be done in this way:
```
fI÷<A
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiIiwiZknDtzxBIiwiIiwiXCJhYlwiXG5cImFhYmJcIlxuXCJhYWFiYmJcIlxuXCJhYWFhYmJiYlwiXG5cImFhYWFhYmJiYmJcIlxuXCJhYWFhYWFiYmJiYmJcIlxuXCJcIlxuXCJhXCJcblwiYlwiXG5cImFhXCJcblwiYmFcIlxuXCJiYlwiXG5cImFhYVwiXG5cImFhYlwiXG5cImFiYVwiXG5cImFiYlwiXG5cImJhYVwiXG5cImJhYlwiXG5cImJiYVwiXG5cImJiYlwiXG5cImFhYWFcIlxuXCJhYWFiXCJcblwiYWFiYVwiXG5cImFiYWFcIlxuXCJhYmFiXCJcblwiYWJiYVwiXG5cImFiYmJcIlxuXCJiYWFhXCJcblwiYmFhYlwiXG5cImJhYmFcIlxuXCJiYWJiXCJcblwiYmJhYVwiXG5cImJiYWJcIlxuXCJiYmJhXCJcblwiYmJiYlwiIl0=)
Takes a string as input. Outputs `1` for true and `0` for false.
This too is just one of the above 4 byte programs with `f` inserted at the beginning – but it can also be done without `f`, using a conceptually similar algorithm:
```
½C÷‹⁼
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiIiwiwr1Dw7figLnigbwiLCIiLCJcImFiXCJcblwiYWFiYlwiXG5cImFhYWJiYlwiXG5cImFhYWFiYmJiXCJcblwiYWFhYWFiYmJiYlwiXG5cImFhYWFhYWJiYmJiYlwiXG5cIlwiXG5cImFcIlxuXCJiXCJcblwiYWFcIlxuXCJiYVwiXG5cImJiXCJcblwiYWFhXCJcblwiYWFiXCJcblwiYWJhXCJcblwiYWJiXCJcblwiYmFhXCJcblwiYmFiXCJcblwiYmJhXCJcblwiYmJiXCJcblwiYWFhYVwiXG5cImFhYWJcIlxuXCJhYWJhXCJcblwiYWJhYVwiXG5cImFiYWJcIlxuXCJhYmJhXCJcblwiYWJiYlwiXG5cImJhYWFcIlxuXCJiYWFiXCJcblwiYmFiYVwiXG5cImJhYmJcIlxuXCJiYmFhXCJcblwiYmJhYlwiXG5cImJiYmFcIlxuXCJiYmJiXCIiXQ==)
Takes a string as input. Outputs `1` for true and `0` for false.
```
½   # Split in half. If odd in length, the left side gets 1 more character. This
    # creates a list containing two strings.
C   # Convert characters to their ASCII values. This results in a list containing
    # two lists of ASCII values.
÷   # Item Split - split the list into its elements on stack; in this case, these
    # are the left and right halves, each of which is a list of ASCII values.
‹   # Decrement - iff the right half is all 'b' (ASCII 98), this will change it to
    # all 'a' (ASCII 97)
⁼   # Are the two top items on the stack exactly equal? This gives a boolean value
    # that's 1 for true (equal counts of 'a' and 'b') and 0 for false.
```
# [Vyxal](https://github.com/Vyxal/Vyxal), 5 bytes
```
AḂs꘍↓
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiIiwiQeG4gnPqmI3ihpMiLCIiLCJcImFiXCJcblwiYWFiYlwiXG5cImFhYWJiYlwiXG5cImFhYWFiYmJiXCJcblwiYWFhYWFiYmJiYlwiXG5cImFhYWFhYWJiYmJiYlwiXG5cIlwiXG5cImFcIlxuXCJiXCJcblwiYWFcIlxuXCJiYVwiXG5cImJiXCJcblwiYWFhXCJcblwiYWFiXCJcblwiYWJhXCJcblwiYWJiXCJcblwiYmFhXCJcblwiYmFiXCJcblwiYmJhXCJcblwiYmJiXCJcblwiYWFhYVwiXG5cImFhYWJcIlxuXCJhYWJhXCJcblwiYWJhYVwiXG5cImFiYWJcIlxuXCJhYmJhXCJcblwiYWJiYlwiXG5cImJhYWFcIlxuXCJiYWFiXCJcblwiYmFiYVwiXG5cImJhYmJcIlxuXCJiYmFhXCJcblwiYmJhYlwiXG5cImJiYmFcIlxuXCJiYmJiXCIiXQ==)
Takes a string as input. Outputs `1` for true, and empty string or `0` for false.
This is an adaptation of the algorithm used in [Dennis's Jelly answer](https://codegolf.stackexchange.com/a/86034/17216) and [MATL answer](https://codegolf.stackexchange.com/a/86037/17216) (and many subsequent answers):
```
A   # Check if character is a vowel (vectorized)
    # Converts each 'a' to 1, and each 'b' to 0. Pushes the result as a list if
    # the input was a string of 2 characters or longer, but only pushes a single
    # integer if it was a single-character string. This limits what useful
    # operations can subsequently be done (for example, it can't be reliably
    # split into two halves).
Ḃ   # Bifurcate - Pushes the top of the stack then its reverse.
s   # Sort - Operates on the non-reversed copy.
꘍   # Bitwise Xor (vectorized)
↓   # Minimum by tail. On a list of numbers, it picks the item with the minimum
    # last digit. On a single number, it picks the minimum digit. Since the only
    # numbers given to it here will be 0 and 1, that's the same as the standard
    # minimum, except that it avoids the crash that happens with "g" (Minimum)
    # when its argument is not a list.
```
It appears to be impossible to solve this challenge in Vyxal in less than 5 bytes taking a string as input.
---
Determining membership in \$\{a^n b^n:n∈\mathbb{Z}^0\}\$ can also be done in this way:
```
AḂs꘍A
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJBIiwiIiwiQeG4gnPqmI1BIiwiIiwiXCJhYlwiXG5cImFhYmJcIlxuXCJhYWFiYmJcIlxuXCJhYWFhYmJiYlwiXG5cImFhYWFhYmJiYmJcIlxuXCJhYWFhYWFiYmJiYmJcIlxuXCJcIlxuXCJhXCJcblwiYlwiXG5cImFhXCJcblwiYmFcIlxuXCJiYlwiXG5cImFhYVwiXG5cImFhYlwiXG5cImFiYVwiXG5cImFiYlwiXG5cImJhYVwiXG5cImJhYlwiXG5cImJiYVwiXG5cImJiYlwiXG5cImFhYWFcIlxuXCJhYWFiXCJcblwiYWFiYVwiXG5cImFiYWFcIlxuXCJhYmFiXCJcblwiYWJiYVwiXG5cImFiYmJcIlxuXCJiYWFhXCJcblwiYmFhYlwiXG5cImJhYmFcIlxuXCJiYWJiXCJcblwiYmJhYVwiXG5cImJiYWJcIlxuXCJiYmJhXCJcblwiYmJiYlwiIl0=)
Takes a string as input. Outputs `1` for true and `0` for false. Only the last element of the program is different:
```
A   # Check if all items in a list are truthy (returns truthy for an empty list)
```
[Answer]
The purpose of this post is to demonstrate and explain the full list of golfed pure regexes that solve this challenge, and the range of compatibility of each among seven different regex engines, and rank them by length, all together in one post. Others' answers used the best regexes before this post; they are listed below. I ported the **Java** one to three other sets of regex engines, including Python 3's `regex` library.
# Regex (Perl / PCRE / Boost / Python[`regex`](https://bitbucket.org/mrabarnett/mrab-regex/src/hg/)), 11 bytes
```
^(a(?1)?b)$
```
[Try it online!](https://tio.run/##TYxBa8MwDIXv/hWiGGJDR5rDLnHTUOh27KnHUWONFAJe2zntYYT0r2eSXNjASM9673vXLsXX@esHdHIwxstniKBLR99mvdsetptJnS7J6L5ZufXG0a7sCP2JLna8pv58g8XHeeEm0BEaGO443Cjuly/VsrLdN5vQ/ruvyLFQg/ZOAeQGYxh@QKlTadvikO5dDVDUxXuIA8nC/mV1dDB5/7bfeT8fTTBtZVu0ep4DqhCQB01ZvLMQ9ZRZo1JB8UUhPbEYV4G@3ILi0BY7o1LNKY4EGQxkQhBmGOIISo305KLchL8 "Perl 5 – Try It Online") - Perl  
[Try it online!](https://tio.run/##fVJRT9swEH7Przi6MWwWULtKe2ha0IZAe2AwVUzaBCxy0ksaLU0sx1lHUf/6ujs7ZYWHRZF9vvu@785fkmp9lKfp5lVRpWU7Qxjr1ODx/CRI58pArG/vYQLT3sfl8mcybL8/PHy7mb9fzsXmh1DidCBPE/l6I1@WeyEc6kms3w6i4J90Y2dFzdq7KVNU@fNcUVMW1eIkKCoLmgA2RmNqI9K6aiy4yQ4X2DQqR/lIqqNRSgAYj6HLcujyWM3KCAza1lQwiNZOcqGKSkh4DIAefUvdSqyElkeD@0k/gpYww3exhZpPTMgpcGCn6Wemgm5tBOwXHBqMYHc6Gkdb49kGm7a0PuZ7ZFmDNoS6tdQ2t3NfqX9hamtzO7z3rUh14sTjtF7ookShQ@iH8MZL@2Cr1ZeeVGQg9gzK7Y0z514maG5Ch9D7cjY9d0MYUNTT0WF/NoL95q6ir7aj6ft0whkRBI@5Yk@cDTnasqhQeP@LKvSOyIgwg62726FWEqjG3oiDu@qgU/X3ZHe2d8XfmAqDIVx9vbzsFI/TmCwXcntsihXyqe/ezrcQhjui3LITHpM5O8O8qO5NgC2Jz6fT62l8df35w83ZJwmdbb1zdmoEPboUlg0@5S8UnVz@SXj9HHFjWgI8Q2RLU1gU/73TIGRza7bR8dbefYNIE8unP7n7pYL1RiWBUgkvtLqNdx@4qAt9nASBCjgTJPS6EtMDRUdWSVyFdlf2VCfNKIYotzDBMxyFOUxiSOJknI4X8krJnzQrVd5sjkr@zn8B "C++ (gcc) – Try It Online") - PCRE1  
[Try it online!](https://tio.run/##XZDNboMwEITvPIVrWYpdkR@ucRGXkipSlVQ0t9JaNjIByRBkyKnqs9Nd01Ml7B3vznwYhmaYn7KhGQjzJCV0S8mGDN5elbeD05Xlq@3mMVOq0W5S1a0bWmd9yUshy2I7rmKyglVDU10tGvrJ9tPIlTocX3OlREwSAUgAy6i@ec7adCeZS2uwj/z98nw8CSm@SVtz5j7GyTvbgxLr5DNNadlTAebxbmAC7XgXrxMhg7sVtmpuaJEEqImMCGFdGi7f6alqOPMxkCRB3/JRTo@Tst7DRcRD@lbkL@p0VnlRnIuM5tjfE7rnrMvoxd/tnsCJHrQbQVKBbwgsyhyVP/9@Chdy/uKaZ4nIjGDzrE2ktcEN9lCwLiKoP7loE0U6wk5k4AkjjEcajkgxYQI1jJdoQKMLLTpsGFgSIYIZDKHFBEzgLKCFZH4B "PHP – Try It Online") - PCRE2  
[Try it online!](https://tio.run/##XVDbbpwwEH33V4xopNgtuy2N1AfoZqU@9AOqPLRKUmQ7BqywxjJGNFvl10s8Q65FaDzjM@fM8WjvN63WyzvrdD/dGPiqhmGMH4NpzZ9t5/05050MUPvLa9jBj@zbPN@qs@nX3d3Pi@7L3PHlN5d8X4i9EieL@B/Ocnjvd7X/UFTsZYZNI4KRh3NmXYSDtI4L@Msgff4yQb1x3ItNcb37VMGUes4@1xEGrJDQpoSax3hTlqnfujYBfooV6MGNEegRZUmvgGC4z99claXVcjSierodDzLqDuZOxlW5GQJwnHXEoTSnNbG3znAqtHX5OjKJHHfFk338bAP8KCBhuDp@euVORfWM@uQ2Nvy1nXo0MuiOk15OLvLkWsAesoswmRIggxKy77IfU5G9UmvmYKNZmVtdp11w8WhsO9qjwarI8QEDWiXePcVg4hQcpE3eL1IxKRWGFOnAc00oe0zXXDEmGd4wlX6CkM5kKlFFEZJOglcqSWMXtkgKSFgZREEOkrBFkQzprEKrkvqnm16247LpaX01be8B "C++ (gcc) – Try It Online") - Boost  
[Try it online!](https://tio.run/##bY5BagMxDEX3PoUwhdiQDhm6czHZ9QTdTVuQG6cxuJ5B49Dm9FNLzrJgpC/p/4eXW73M5WlL38tMFdbbuqf4FX8VgQfSWm8fBs1xtMdgH7Y2T6N7HN@fIfmDOs8EGVLh2LDWUypOAaQzJAcLpVKN5dmPfZtjMdkClhPkqUG8372VnYPs83RgarPdSfO1Dj@UajT6la7RAWgmyNeGNSJ9XgztodFiXiPoF2zNgbb/IbLdMCjEwKVVady7EHWXXQelUPFGhfbkxHGFbWRKkEvrcu5RQbOLLSiFAz0hEc5wiC1BMMLpoE4Kfw "Python 3 – Try It Online") - Python `import regex`
Included for completeness. Already used in:
* [Martin Ender's Mathematica answer](https://codegolf.stackexchange.com/a/86104/17216)
* [Titus's PHP answer](https://codegolf.stackexchange.com/a/86365/17216)
* [Paul Picard's Perl answer](https://codegolf.stackexchange.com/a/86006/17216)
```
^          # Assert we're at the beginning of the string.
(          # Define subroutine (?1):
    a      # Match one 'a'.
    (?1)?  # Optionally do a recursive subroutine call to (?1).
    b      # Match one 'b'.
)
$          # Assert we're at the end of the string.
```
When the regex engine hits the `(?1)?`, it has the choice of whether to do the call or not. Due to `?` being greedy by default, it first tries doing the call; if it then hits a `b` character instead of an `a`, it will backtrack, avoid doing the subroutine call, and then reach the part of the regex that matches a `b` character.
From that point forward, it will keep popping out of the recursive call stack, matching another `b` each time. This way, the number of times that it attempts to match `b` equals the number of `a` it matched at the beginning.
If it finds an `a` when attempting to match `b`, this will trigger a non-match. If it finishes popping and still finds more `b` characters, this will trigger a non-match at the `$` part of the regex. If it reaches the end of the string prematurely during this stage, it will pop out from that call and attempt to match another `b`, thus triggering a non-match.
The only backtracking left to be tried at the popping-out stage, in the case of any of those non-matches, is to stop calling `(?1)` at an earlier point, but this will also fail to match, as it will then be trying to match `a` where the string has a `b`; this will result in a top-level non-match.
# Regex (PCRE / Ruby), 12 bytes
```
^(a\g<1>?b)$
```
[Try it online!](https://tio.run/##fVJRb9MwEH7Pr7gVxpyRTS2VeGjaIZiGeBgbqoYE2kbkuJc0Ik0sx6FsU/865c5OS7sHosg@333fd@cvUVqf5EqtXxSVKtsZwlgrg6fzs0DNpYFE397DBKa9D8vlz3TYfn94@HYzf7uci/UPIe/y8eDsXRq@XIfP670IjvUk0a8HcfBPu7Gzombx3ZQpqnw/V9SURbk4C4rKgiaATdCY2ghVV40FN9rxAptG5hg@kepopAgA4zF0WQ5dHqtZGYNB25oKBvHKSS5kUYkQngKgR99StxIrocOTwf2kH0NLmOGbxELNJybkFDiw0/QzU0G3NgY2DI4NxrA7HY2jrfFsg01bWh/zPbKsQRtB3Vpqm9u5r9S/UNna3A7vfStSnTjxRNULXZQodAT9CF55aR9stPqhJxUZiAOD4ebGmXMvEzQ3oSPofTmfXrghDEjq6ehwOBvBYXNX0Vfb0fR9OuGMCILHfGRPnA052rKoUHj/iyryjoQxYQYbdzdDPYZANfZGHN1VR52qvye7s7kr/kYlDEZw9fXyslM8VQlZLsLNsSkekU9993a@RTDcEeWWnfCYzNkZ5ln1YAJsSXIxnV5Pk6vrz@9vzj@F0NnWu2CnRtCjS2HZ4Db/UdLJ5bfCq33EjWkJsIfIlqawKP57p0HE5tZso@OtvPsGkSYOt39y90sFq7VMAylTXmh1G@8@cFEX@jgNAhlwJkjpdSWmB5KOrJK6Cu2u7KlOmlEMkW5hgmc4CnOYxJDUyTgdL@SV0j8qK2XerE9K/s5/AQ "C++ (gcc) – Try It Online") - PCRE1  
[Try it online!](https://tio.run/##XZDNboMwEITvPIVrWYpdkR@ucSiXkipSlVQ0t9JaNjIBySHIkFPVZ6e7pqdK2Dvenfkw9E0/7bK@6QnzJCV0TcmK9N5elLe905Xli/XqMVOq0W5U1e3at876kpdClsV6WMRkAauGprpYNHSj7caBK7U/vOZKiZgkApAAllF985y16UYyl9ZgH/j7@flwFFJ8k7bmzH0Mo3e2AyWWyWea0rKjAszD3cAE2vEmXiZCBncrbNXc0CIJUBMZEcKuabj8VY9Vw5mPgSQJ@uaPcnoYlfUeLiIe0rcif1HHk8qL4lRkNMf@ltAtZ9eMnv3dbgmc6F67ASQV@IbAosxR@fPvp3Ahpy@uy8suecqMYNOkTaS1wQ32ULDOIqg/OWsTRTrCTmTgCSOMRxqOSDFhAjWM52hAowstOmwYmBMhghkMocUETODMoJlkfgE "PHP – Try It Online") - PCRE2  
**[Try it online!](https://tio.run/##RYzBasMwEETv@oqpyKE9xMQ9RlVDIO0xh5JbkhotUV2BMEa2SXPJr7vaVaEgdmc18yZNdJsTLD5863/6qvNX7LaHbZW8uxgEuzK4fofoEW3rx0EB4Qvhgf/7aRwMfCe52rARj8v6bK0@ddpkIh5XVbV8Pksqo30K3YgIe0fCBvqQJr8GNNbQ7y4O@dD/sUI1zdt@1zTz56M7tS/164aeFvPsSDlHPPKUxbsIUX@yaFLKKf5RlJ9YjCuXT24hcfIWu6BSzSmOOBkMFEIQZhjiCEmN9JSi0kS/ "Ruby – Try It Online") - Ruby**
Included for completeness. Already used in [G B's Ruby answer](https://codegolf.stackexchange.com/a/182021/17216).
This is the same as the 11 byte version, but using Ruby's subroutine call syntax.
# Regex (Perl / PCRE / Java), 21 bytes
```
^(a(?=a*(\2?+b)))+\2$
```
[Try it online!](https://tio.run/##TYxBi8IwEIXv@RWDBJqsLrXCXhprEVyPnjyWDZOlQiGrbqoHKfWvd2eShV0IMy/z3veubfBv09cDZDAw@MsnepC5oW@13m2P280oTpegZFctzXpjaBd6gO5EFz1cQ3e@waw5z8wI0kMF/d31N4rbxWuxKHT7zSbU/@5LcjSUIK0RAKlBKYafkMuQ6zo7hntbAmRltkffk8z0X1Z6A6O174edtdOHQlVX@KKaVT13Wut5s5LThE4gOh404@KdRFS/MmknBAq@CEcvWowLpC@3uOjQjnZCYzWnOIJxMJCIiDDDEEdcrIk9qSg1uR8 "Perl 5 – Try It Online") - Perl  
[Try it online!](https://tio.run/##fVJRT9swEH7Przi6MewSUEulPTQtaEOgPTCYqk7aRFnkuE4aLU0sx1kHqH993Z2ddoWHRZF9vvu@785fIrU@yaTcvMlLWTRzBSMtjTpdnAdyIQzE@v4BxjDpfFytfiaD5vvj47fp4v1qwTY/mGAXY9Fls7OL44Rzfjw7e7vhr4GdELp6HOvjfhT8a1LbeV5Rl/2UycvsZS6vMKvE8jzISwsaATZWxlSGyaqsLbgZu0tV1yJT/BlVh0OJABiNoM1S6PKqnBcRGGUbU0I/WjvJpchLxuE5AHz0PXYrVMk0P@k/jHsRNIgZnMUWKjoRIcPAgZ2mnxkLurERkHPQNSqC/elwHG2NZxtVN4X1Md0jTWtlQ6gai20zu/CV6peStjL3gwffClXHTjyW1VLnhWI6hF4I77y0D7ZaPe5JeQrswCi@vXHq3EsZzo3oEDpfLidXbggDAns6OhzOh3BYz0r8anuavk8rnCKB0ZhP5ImzIVO2yEvFvP95GXpHeISY/tbd7VBPHLBG3rCjWXnUqvp7kjvbu6rfSjKjQrj9enPTKp7KGC1nfHus8ydFp557W99CGOyJUstWeITm7A3zqnowBrIkvppM7ibx7d3nD9PLTxxa2zpX5NQQOngpVdRql78WeHL5nfD6JWJqGgS8QKQrk1vF/nunfkjmVmSj4629@0YpnJjv/uT2lwrWG5EEQiS04Oo22n3gojb0cRIEIqBMkODrSkQPBB5JJXEV3F3ZU500oQgi3EIEz3AU4hCJIImTcTpeyCslf2RaiKzenBT0nf8C "C++ (gcc) – Try It Online") - PCRE1  
[Try it online!](https://tio.run/##XZBRb4MgFIXf/RWMkBRa284@lhFfZpcmS7u4vs2NgMFqgtagfVr2290F97REuId7z/lE@7qfntK@7hFxSCC8xWiDemeu0pneqtLQxXazTKWslR1leWv7xhpX0ILxIt8OixgtYFXQlFfjDd1ounGgUh6Or5mULEYJAySAeVTdHCWNeOTEigrsA32/PB9PjLNv1FSU2I9hdNZ0oNg6@RQCFx1mYB7uGibQjh/jdcJ4cDfMlPXNWzgCasIjhEgrwuVbNZY1JS4GEkfeN3@UVcMojXNwEfYg3vLsRZ7OMsvzc57izPf3CO8paVN8cXezR3DCB2UHkJj5NwQWJhbzn38/hTI@fVFFU6GWtNilK80YWxU7Mk1KR0ppv8Eeiq@zCOpPzlpHkYp8J9LwhJGPRwqOnqLDBGoYz9GA9i5vUWHzgTkRIj7jQ96iAyZwZtBM0r8 "PHP – Try It Online") - PCRE2  
**[Try it online!](https://tio.run/##bZHfb9MwEMff81fcIqTZLWRjj4usSkjsCRCivFEm2YnTukucYDtrUZW/vdzZAW2oUmTfr@/nfJe9fJbv9vXT2XRD7wLs0S9MXyxKeBkZg2kvxpze6iNlhlG1poKqld7DZ2ksnOaQDzLg9dybGjpMsHVwxm5Buq3/8ZND2Ln@4OHjsdJDMD0KM4AH02pohNWHaLK8qPpaF5jPeflhbBrtdP1Ny1o7ULHsdZD9Vc5uw3k59/VvQ3nYEZ8xLxSOIOtPxmrG@ZWwY9ty0zBf6F@jbD3LbxaLRc756XVpIjAWLgJOSAj/CAi4QYLCuqfSL8X1xl7THcopxaavMgTtLDgxWzhtN1ADz0vcxrqS1uKkxg5jAAE03Bxj698@6K4wluPvsQGMuC1hni/WFzvpv@hjwOfBCfBl5krc8lnWY37AtYTWMgKI99QPO6ZdtdgsQSwS5tHx94Zqh8/pMOuKLnmsxcz/1IZ1RWNszTisIP/uRn0PkMM95A@4GnTyCyIiTdOU0ebPj0yylZALtrlbLRXnfLm5e3OmlZ6lyqRUdOAZL7qTEa3ZTLbKMplRJFP4xRTJM4kuUVTM4B3TSRrRVEUlMh4kSIooIQ2JqERFTOQkUCKpPw "Java (JDK) – Try It Online") - Java**
Turned out to be used in [Kevin Cruijssen's Java answer](https://codegolf.stackexchange.com/a/86061/17216), but gave it a -6 byte golf.
This regex is the next-best thing to recursion, in engines that lack it. It works using group-building:
```
^           # Assert we're at the beginning of the string.
(
    a       # Match one more 'a' per each iteration of this loop.
    # Lookahead assertion - when this finishes, the regex engine's "cursor"
    # will jump back to the same position as it was in when it entered the
    # lookahead here. It's atomic, so the regex engine can't backtrack into
    # the lookahead once it has completed its match or non-match. This means
    # the main loop will exit immediately if this lookahead fails to match
    # (due to running out of 'b' characters to match), or if the 'a' above
    # fails to match.
    (?=
        a*      # Skip over as many 'a' as necessary to get to the first 'b'.
        # Capture \2, embedding within it the previous contents of itself.
        # If this is the first iteration, \2 will be unset, so capture a
        # single 'b' in \2. Otherwise, append one more 'b' to the previous
        # contents of \2.
        (
            \2?+    # Optionally match \2, but if it does match, lock that
                    # match in (don't backtrack to here and try not making the
                    # match, in the case that a non-match occurs after this
                    # point). This is guaranteed to fail to match if and only if
                    # we're on the first iteration, due to \2 being unset. On
                    # subsequent iterations, since \2 will have been captured
                    # starting at the first non-'a' character, and always starts
                    # its attempted match there, it will be guaranteed to match.
            b       # Match one 'b'.
        )
    )
)+
\2          # Match however many 'b' we captured in \2.
$           # Assert we're at the end of the string.
```
# Regex (.NET), 22 bytes
```
^(a)+(?<-1>b)+$(?(1)^)
```
[Try it online!](https://tio.run/##RY3BasMwEETv@gphBJJIXOqr3TSBQG@99VYaWKXrWqDKRnZwifG3u1qpUDA7s955o6GfMYwdOreJcHgP@IU/H3XtcVYnuV0U6J06PpXVs9E7oY6q0he9ydO@OPffg3X4WehG3A@PTdsHhGunhOPWc2H9cJv0Ylsl7nqZg52w7PpxWmO4av53Xvo@PuasR14IZVuuRHh4hena4RjLtOaLfAs3rLlcOboR4/4CUWu5ai5csW5gGIChEWcS0myS@7PZG8aA0R9m4pdOhDOIK7WYdImazhlN1ZSiCKRBQCYSQgxBFDGpJvXkotxkfgE "PowerShell – Try It Online")
Included for completeness. Already used in:
* [Leaky Nun's Retina answer](https://codegolf.stackexchange.com/a/86002/17216)
* [AdmBorkBork's PowerShell answer](https://codegolf.stackexchange.com/a/86011/17216)
* [Dion Williams's C# answer](https://codegolf.stackexchange.com/a/86300/17216) (with regex 7 bytes longer than it needs to be)
This regex uses the Balancing Groups feature of the .NET regex engine:
```
^           # Assert we're at the beginning of the string.
(a)+        # Match as many 'a' characters as we can, minimum of one, pushing
            # each single-character capture onto the Group 1 capture stack.
(?<-1>b)+   # Pop the Group 1 capture stack as many times as we can, matching
            # a single 'b' each time. This will stop looping when it hits a
            # character other than 'b', or empties the Group 1 capture stack.
$           # Assert we're at the end of the string. If this fails to match
            # (meaning there are more 'b' characters than 'a' characters), the
            # regex engine will backtrack, but none of the choices it has will
            # be able lead to a match, so there will be a top-level non-match.
(?(1)^)     # If there are any remaining captures on the Group 1 stack (which
            # means there were fewer 'b' characters than 'a' chracters), assert
            # something which can never be true - that we're at the beginning
            # of the string. Since the first thing the regex did was capture at
            # least one 'a', the fact that we've reached this point means that
            # was already done, so it's impossible for us to be at the beginning
            # of the string. Thus this causes a non-match in the case that there
            # are fewer 'b' than 'a'.
```
Some people use this regex in the form of `^(a)+(?<-1>b)+(?(1)^)$`, i.e. with the `$` at the end rather than the beginning, but I prefer `^(a)+(?<-1>b)+$(?(1)^)`, since it tries the slightly-less-complicated operation of `$` first, so in the case of a non-match, it will be ever so slightly more efficient. In theory.
The `^` in the `(?(1)^)` can be replaced with various other things that can't match, such as `(?(1).)` or `(?(1)c)`.
# Regex (Perl / PCRE / Java / .NET), 24 bytes
```
^(a(?=a*((?>\2?)b)))+\2$
```
[Try it online!](https://tio.run/##TYzNasMwEITveoolCKxtExwHcrFim0DaY085mgqpOGBQ8yMnh2LcV3d3pUILYne0M99cu@C38@cXyKBh9JcP60Hmmr7V7rA/7utJnC5Byb5a612taRc4Qn@iC47X0J/vsGjPCz2B9FDB8HDDneJmuSqWBXY3NqH5d1@Tg1CCNFoApAalGP6GXIYcm@wYHl0JkJXZq/UDyQz/stJrmIx5eTsYM78rq5rKPinV1O2mQYeIz@1GzrN1wlrHg2ZcvJOI6lcm7YSwgi/C0YsW48LSl1tcdGhHO6GxmlMcsXEwkIiIMMMQR1ysiT2pKDW5Hw "Perl 5 – Try It Online") - Perl  
[Try it online!](https://tio.run/##fVJRT9swEH7Przi6MewSUEulPTQtaEOgPTCYqk7aRFnkuE4aLU0sx1kHqH993Z2ddoWHRZF9vvu@785fIrU@yaTcvMlLWTRzBSMtjTpdnAdyIQzE@v4BxjDpfFytfiaD5vvj47fp4v1qwTY/mGAXY9Fl7OJ8dnbBE8758ezs7Ya/xnZC6OpxrI/7UfCvT23neUWN9lMmL7OXubzCrBLL8yAvLWgE2FgZUxkmq7K24MbsLlVdi0zxZ1QdDiUCYDSCNkuhy6tyXkRglG1MCf1o7SSXIi8Zh@cA8NH32K1QJdP8pP8w7kXQIGZwFluo6ESEDAMHdpp@ZizoxkZA5kHXqAj2p8NxtDWebVTdFNbHdI80rZUNoWosts3swleqX0raytwPHnwrVB078VhWS50XiukQeiG889I@2Gr1uCflKbADo/j2xqlzL2U4N6JD6Hy5nFy5IQwI7OnocDgfwmE9K/Gr7Wn6Pq1wigRGYz6RJ86GTNkiLxXz/udl6B3hEWL6W3e3Qz1xwBp5w45m5VGr6u9J7mzvqn4ryYwK4fbrzU2reCpjtJzx7bHOnxSdeu5tfQthsCdKLVvhEZqzN8yr6sEYyJL4ajK5m8S3d58/TC8/cWht61yRU0Po4KVUUatd/lrgyeV3wuuXiKlpEPACka5MbhX77536IZlbkY2Ot/buG6VwYr77k9tfKlhvRBIIkdCCq9to94GL2tDHSRCIgDJBgq8rET0QeCSVxFVwd2VPddKEIohwCxE8w1GIQySCJE7G6Xghr5T8kWkhsnpzUtB3/gs "C++ (gcc) – Try It Online") - PCRE1  
[Try it online!](https://tio.run/##XZBfb4MgFMXf@RSMkBQ6@8c@ljlfZpcmS7e4vs2NgMFqgtagfVr22d0F97REuId7z/mJ9nU/PaR93WPqcILJhuA17p25SGd6q0rDFpv1MpWyVnaU5bXtG2tcwQouinwzLCK8gFVBU16MN3Sj6caBSXk4vmRS8gjHHJAAFqi6OkabZCuoTSqwD@z9/HQ8ccG/cVMxaj@G0VnTgeKr@DNJSNERDubhpmEC7WgbrWIugrvhpqyv3iIwUGOBMKZtEi7fqrGsGXURkAT2vvmjrBpGaZyDi/C75C3PnuXpVWZ5/pqnJPP9PSZ7RtuUnN3N7DGcyEHZASTh/g2BRagl4uffT2FcTF9MsTRRS8bSx2KXcs05vy92dJqURkppv8Eeiq@zCOpPzlojpJDvIA1PGPk4UnD0FB0mUMN4jga0d3mLCpsPzIkQ8Rkf8hYdMIEzg2aS/gU "PHP – Try It Online") - PCRE2  
[Try it online!](https://tio.run/##bZHfb9MwEMff81fcIqTZHWRjj4tMJST2BAhR3uiQ7MRp3SVOsJ21qMrf3t3ZYWKoUmTfr@/nfJedfJLvdvXjyXRD7wLs0C9MXyxK@DcyBtOejTm90QfKDKNqTQVVK72HL9JYOM4hH2TA66k3NXSYYKvgjN2AdBv/84FD2Lp@7@HTodJDMD0KM4B702pohNX7aLK8qPpaF5jPeflxbBrtdP1dy1o7ULHsdZD9Vc5uw3k59/VvQ7nfEp8xLxSOIOvPxmrG@YWwY9ty0zBf6N@jbD3LrxeLRc758XVpIjAWzgKOSAgvBARcI0Fh3WPpr8Tl2l7SHcopxaZvMgTtLDgxWzhtN1ADz0vcxqqS1uKkxg5jAAE03Bxjqz8@6K4wluPvsQGMuClhni/WF1vpv@pDwOfBEfBl5kLc8FnWY37AtYTWMgKI99QPO6ZdtdgsQSwS5tHx94Zqi8/pMOuKLnmsxcz/1IZ1RWNszTgsIf/hRn0HkMMd5Pe4GnTyMyIiTdOU0eZPv5hkSyEXjC0/rG@XXHHOr9a3b0601ZNUmZSKDjzjRXcyojWbyVZZJjOKZAq/mCJ5JtEliooZvGM6SSOaqqhExoMESRElpCERlaiIiZwESiT1DA "Java (JDK) – Try It Online") - Java  
[Try it online!](https://tio.run/##RY1BS8QwEIXv@RWhBJqoK7rHltoFwZs3b67CZHdqAzEpaZfKlv72mkkEocx703nfy@BnDGOP1m4iNO8Bv/Dno6oczvJQbp8SZNvAjZTt03HfKq2Uuj3uxVYe7opn/z0Yi@dC1eLaPNSdDwinXgrLjePCuOEyqcV0UlzVMgcz4a7347TG8GP9v/Od8/E5axzyQkjTcSnC/StMpx7HWKYUX8q3cMGKlytHO2LcXyBqVa6KC1usG2gGoGnEmYQ0m@T@bPaaMWD0h@n4pRPhDOJKLTpdoqZzRlM1pSgCaRCQiYQQQxBFdKpJPbkoN@lf "PowerShell – Try It Online") - .NET
This is a port of the **21 byte** Perl/PCRE/**Java** regex, with `\3?+` changed to `(?>\3?)` to allow the regex to also work on .NET (which lacks possessive quantifiers).
# Regex (Perl / PCRE / Java / Ruby / Python[`regex`](https://bitbucket.org/mrabarnett/mrab-regex/src/hg/)), 29 bytes
```
^(a(?=a*(?=(\3?+b))(\2)))+\2$
```
[Try it online!](https://tio.run/##TUzLasMwELzrK5YgsLZJcJzQixXHBNIee8rRVEjFAYOah5wcinF/3d2VCi2ImdHO49oG/zx9foEMGgZ/@bAeZK7pW20P@@N@N4rTJSjZVSu93WniAgfoTnTB4Rq68x1mzXmmR5AeKugfrr9T3CyWxaLA9sYm1P/uK3IQSpBGC4C0oBSXvyGXIcc6O4ZHWwJkZfZqfU8yw7@s9BpGY17eDsZM78qqurJPBKrZ1HOHqJo1Is6btZwm64S1joEwEnMSUf3KpJ0QVvBFOHrR4rqw9OUVFx3iaKdqnOYUR2wELqRGrHCHSxxxcSbupKG05H4A "Perl 5 – Try It Online") - Perl  
[Try it online!](https://tio.run/##fVJRT9swEH7Przi6MewSUEulPTQtaEOgPTCYqk7aRFnkuE4aLU0sx1kHqH993Z2ddoWHRZF9vvu@785fIrU@yaTcvMlLWTRzBSMtjTpdnAdyIQzE@v4BxjDpfFytfiaD5vvj47fp4v1qwTY/mGAXY9HFhc0GF8cJ52x2xjk/np293fDXhE4IXT2O9XE/Cv41q@08r6jbfsrkZfYyl1eYVWJ5HuSlBY0AGytjKsNkVdYW3KzdpaprkSn@jKrDoUQAjEbQZil0eVXOiwiMso0poR@tneRS5CXj8BwAPvoeuxWqZJqf9B/GvQgaxAzOYgsVnYiQYeDATtPPjAXd2AjIQegaFcH@dDiOtsazjaqbwvqY7pGmtbIhVI3Ftpld@Er1S0lbmfvBg2@FqmMnHstqqfNCMR1CL4R3XtoHW60e96Q8BXZgFN/eOHXupQznRnQInS@Xkys3hAGBPR0dDudDOKxnJX61PU3fpxVOkcBozCfyxNmQKVvkpWLe/7wMvSM8Qkx/6@52qCcOWCNv2NGsPGpV/T3Jne1d1W8lmVEh3H69uWkVT2WMljO@Pdb5k6JTz72tbyEM9kSpZSs8QnP2hnlVPRgDWRJfTSZ3k/j27vOH6eUnDq1tnStyaggdvJQqarXLXws8ufxOeP0SMTUNAl4g0pXJrWL/vVM/JHMrstHx1t59oxROzHd/cvtLBeuNSAIhElpwdRvtPnBRG/o4CQIRUCZI8HUlogcCj6SSuAruruypTppQBBFuIYJnOApxiESQxMk4HS/klZI/Mi1EVm9OCvrOfwE "C++ (gcc) – Try It Online") - PCRE1  
[Try it online!](https://tio.run/##XZDNbsIwEITveQrXsoQXwk/oDdfKpVAhVVCl3JrWsiNDkByInHCq@ux07fRUKV6Pd2e@OGnr9v6Ut3VLmCeS0DklM9J6e1Letk5Xlo/ms3GuVK1dr6pr056d9SUvQZTFvBulZITriE11ssFw6e2l77hSm@3rWilISQaIRLBIjlfP2VkuBHPyiPaOvx@etzsQ8E3OR87cR9d7Zy@oYJp9SknLCwU0dzeDE2yni3SagYjuM9iqvgaLIEjNREIIa2S8fKP7qubMp0gSJPiGj3K665X1Hi8CD/KtWL@o3V6ti2Jf5HQd@itCV5w1OT34m10RPNGNdh1KCuENkUWZo@Ln30/hIO5fXPNc6jEWXj7mEwPAyyUATMolu9@1SbQ2oWCNW9gHEdWfHLRJEp2ETmLwiaMQTzQeA8XECe5xPEQjOriCRccSAkMiRkImhILFREzkDKCBZH4B "PHP – Try It Online") - PCRE2  
[Try it online!](https://tio.run/##bVHfb9MwEH7PX3GLkGankI3xtsiqhMSeACHKGwXJTpzWXeIE21mLqv7t3Z0dEEOVovv13fed77KTT/LNrnk8m34cXIAd5qUZyqKCfytTMN3FmtMbfSBknFRnaqg76T18ksbCcS75IAO6p8E00CPAVsEZuwHpNv77Dw5h64a9hw@HWo/BDEjMAB5Mp6EVVu9jyPKyHhpdIp7z6v3Uttrp5quWjXagYtvLIvvDnNOW82qe61@Har8lfca8ULiCbD4aqxnnV8JOXcdNy3ypf02y8yy/KYoi5/z4sjUpMBYuChxRIfxVQIEbVFDY91j5hbhe22vyoTql2umLDEE7C07MEW7bjzTA8wqvsaqltbipseMUQAAtN9fY6rcPui@N5fh7bAAjbiuY94v95Vb6z/oQ8HlwBHyZuRK3fKYNiI94ltBZRgLiLc3DielWHQ5LIhYV5tXx94Z6i8/pEXVlnzLWIfK/asv6sjW2YRyWkH9zk74HyOEe8gc8DSb5BRIpnU6njC5//skkWwpZoGHrd8uF4pyt7zjni/XdqzOd9ixVJqUigzY68imI0RymWGWZzKiSKfwiRPRMYkoqKiLoI5yoUZq6qEVGQ4TEiBTiEIlaVJSJOkkoKaln "Java (JDK) – Try It Online") - Java  
[Try it online!](https://tio.run/##RYzBasMwEETv@oqtyMFqiEncW4QwgSTHHkpucWpWVE0FwhjZJumlv@5oV4GCmJ3Vzps42d85goEPd3X3vuzcDfa7066MDr80eLPWcPvxwUEwVzcOAsB/g3@h/34aBw2u49xG0yGcV5uLMbLppE5EOK/LclVdOJXQPvpuhADmDyLUIE9xclsACVuQRwxDWuR/LFNte3jft@38WWBRG3xNUjRv9dIqVTSVUmrZVIt5RisQLUlSHjSzYfe02VshUNCPsOnxiXCBaaUWy5c0@ZxRrqYURZCFgEwwQgxBFLFcwz25KDfZBw "Ruby – Try It Online") - Ruby  
[Try it online!](https://tio.run/##bY5NagMxDIX3PoUwhdhNOuRn52Ky6wm6m2lBbpzE4HoGj0Ob008tOcuCkZ6k9z483ct1TIclfE9jLjDf5032F/8rMljIUsrlU6E6WnyuRQ2H49pprYa91no97J@W6uh35mX38QrBbsV5zBAhJAJ1czmFZARAOEMwMOWQitI0213bRp9U1IDpBLGvEGtXQ1oZiDb2W6JW24M03kr3k0PxSr7nmzcAkgj82W72mL@uKm@g0nycPcg3rM2A1P8hol7QCURHpVZu1Jtg9ZBNOyFQ0Ea4@vhEcYF1JIrjS@18blFGk4ssyIUCLcERylCILI4xzGmgRnJ/ "Python 3 – Try It Online") - Python `import regex`
This is a port of the **21 byte** Perl/PCRE/**Java** regex (see below) adding compatibility with engines that lack nested backreferences, but still have forward-declared backreferences and possessive quantifiers. This allows it to work in Python when using the `regex` library instead of `re`.
```
^           # Assert we're at the beginning of the string.
(
    a       # Match one 'a' per iteration of this loop.
    (?=
        a*  # Skip over as many 'a' as necessary to get to the first 'b'.
        (?=
            # Capture \2. If this is the first iteration, \3 will be unset, so
            # capture a single 'b' in \2. Otherwise, \2 = \3 concatenated with
            # one more 'b'.
            (
                \3?+
                b
            )
        )
        # \3 = make a copy of \2, which was captured above
        (
            \2
        )
    )
)+
\2          # Match however many 'b' we captured in \2.
$           # Assert we're at the end of the string.
```
# Regex (Perl / PCRE / Java / Ruby / Python[`regex`](https://bitbucket.org/mrabarnett/mrab-regex/src/hg/) / .NET), 32 bytes
```
^(a(?=a*(?=((?>\3?)b))(\2)))+\2$
```
[Try it online!](https://tio.run/##TUzLasMwELzrK5YgsLZJcZzSixXbBNIee8rRVEjFAYPyqJwcinF/3d2VCi2ImdHO49oF/zyfvkAGDaO/fFgPMtf0rbb73WFXT@J4CUr21Vpva01c4Aj9kS44XkN/vsGiPS/0BNJDBcPdDTeKm9VjsSqw@2QTmn/3NTkIJUijBUBaUIrL35DLkGOTHcK9KwGyMnu1fiCZ4V9Weg2TMS9ve2Pmd2VVU9kHAqWaun1q0CGqdoOIy3Yj59k6Ya1jIIzEnERUvzJpJ4QVfBGOXrS4Lix9ecVFhzjaqRqnOcURG4ELqREr3OESR1yciTtpKC25Hw "Perl 5 – Try It Online") - Perl  
[Try it online!](https://tio.run/##fVJRT9swEH7Przi6MewSUEulPTQtaEOgPTCYqk7aRFnkuE4aLU0sx1kHqH993Z2ddoWHRZF9vvu@785fIrU@yaTcvMlLWTRzBSMtjTpdnAdyIQzE@v4BxjDpfFytfiaD5vvj47fp4v1qwTY/mGAXY9HFhbGL89nggiecs9kZ5/x4dvZ2w19zOiF09TjWx/0o@NevtvO8oob7KZOX2ctcXmFWieV5kJcWNAJsrIypDJNVWVtw43aXqq5Fpvgzqg6HEgEwGkGbpdDlVTkvIjDKNqaEfrR2kkuRl4zDcwD46HvsVqiSaX7Sfxj3ImgQMziLLVR0IkKGgQM7TT8zFnRjIyAToWtUBPvT4TjaGs82qm4K62O6R5rWyoZQNRbbZnbhK9UvJW1l7gcPvhWqjp14LKulzgvFdAi9EN55aR9stXrck/IU2IFRfHvj1LmXMpwb0SF0vlxOrtwQBgT2dHQ4nA/hsJ6V@NX2NH2fVjhFAqMxn8gTZ0OmbJGXinn/8zL0jvAIMf2tu9uhnjhgjbxhR7PyqFX19yR3tndVv5VkRoVw@/XmplU8lTFazvj2WOdPik4997a@hTDYE6WWrfAIzdkb5lX1YAxkSXw1mdxN4tu7zx@ml584tLZ1rsipIXTwUqqo1S5/LfDk8jvh9UvE1DQIeIFIVya3iv33Tv2QzK3IRsdbe/eNUjgx3/3J7S8VrDciCYRIaMHVbbT7wEVt6OMkCERAmSDB15WIHgg8kkriKri7sqc6aUIRRLiFCJ7hKMQhEkESJ@N0vJBXSv7ItBBZvTkp6Dv/BQ "C++ (gcc) – Try It Online") - PCRE1  
[Try it online!](https://tio.run/##XZDNbsMgEITvPAVFSGFT57e3UNeXOlWkKqnc3OoWgUXiSDixsHOq@uzpgnuqZJZhd@Yzdlu3t8esrVvKPU0pmzE6pa23R@Vt63RlxWg2HWdK1dr1qro07clZX4oSZFnMulFCR7gO2FRHGwzn3p77Tii13rzmSkFCF4BIBEtyuHjBT@lccpce0N6J9/3zZgsSvunpILj76Hrv7BkVTBafacrKMwM0d1eDE2wn82SyABndJ7BVfQkWSZG6kIRS3qTx8o3uq1pwnyBJ0uAbPsrprlfWe7wI3KVvRf6itjuVF8WuyFge@ivKVoI3Gdv7q11RPLG1dh1KBuENkcW4Y/Ln308RIG9fQoss1WMsQmRP5UMGBkCUSwC4L5f8dtOGaG1CwRq3sA8iqj85aEOIJqFDDD5xFOJE4zFQTJzgHsdDNKKDK1h0LCEwJGIkZEIoWEzERM4AGkjmFw "PHP – Try It Online") - PCRE2  
[Try it online!](https://tio.run/##bVHfb9MwEH7PX3GLkGZ3kI3tbVGohMSeACHKG2WSnTitO8cJtrMWVfnby50dEEOVovv13fed77ITz@LNrnk66W7oXYAd5oXui0UJ/1bGoM3ZmlMbdSBkGKXRNdRGeA@fhLZwnEs@iIDuudcNdAiwVXDabkC4jf/@g0PYun7v4cOhVkPQPRIzgAdtFLSVVfsYsryo@0YViOe8fD@2rXKq@apEoxzI2PayyP4w57TlvJzn@teh3G9JnzFfSVxBNB@1VYzzi8qOxnDdMl@on6MwnuXXi8Ui5/z4sjUpMBbOChxRIfxVQIFrVJDY91T6q@pybS/Jh3JKtemLCEE5C66aI9y2G2iA5yVeY1ULa3FTbYcxQAW03Fxjq18@qK7QluPvsQF0dVPCvF/sL7bCf1aHgM@DI@DL9EV1w2daj/iAZwnGMhKo3tI8nJhuZXBYErGoMK@OvzfUW3xOh6grupQxg8j/qi3rilbbhnFYQv7NjeoeIId7yB/wNJjkZ0ikNE1TRpc/PTLBlpVYoGFs@W59t@SSc7a@5ZxfrW9fnei6JyEzISQZtNGRT0GM5jDFMstERpVM4hchomcCU1KREUEf4USN0tRFLSIaIiRGpBCHSNQio0zUSUJJSf4G "Java (JDK) – Try It Online") - Java  
[Try it online!](https://tio.run/##RYzBasMwEETv@oqt6EFqiEncW4RiAmmPPZTc4tSsqJoKhDGyTdpLf93VrgoFMTurnTdpdt9LAguv/uq/hqr3NzgeTocqeXw3EOzGwO0zRA/RXv00CoDwAeGO/od5Gg34nnNbQ4d4Xm8v1sq2lyYT8bypqnV94VRGhxT6CSLYH0jQgDyl2e8AJOxAPmMc8yL/Y4XquqeXY9ctbwpVY/Ehi1LNvn1stNNatbXWetXW98uCTiA6kqw8aBbD7s8W74RAQT/C5ccnwgXmlVocX/Lkc0G5mlIUQRYCCsEIMQRRxHEN95Si0uR@AQ "Ruby – Try It Online") - Ruby  
[Try it online!](https://tio.run/##bY7BbsMgDIbvPIWFJhW2LmraGxPLbU@wW7JJsNIWiZEIqLY@fYZNj5OQ/dv@/08st3KZ42H138ucCuRb3iZ3dr8sgYbEOV8/hRGDNo@1CDG8TodBWinFtJdSPk37h7Waxl499x8v4PWOneYEAXxEVpfL0UfFAPwJvIIl@ViExFn3bRtcFEGCiUcIY4VovZniRkHQYdwhtdrupPlaup/kixP8PV2dAuBIoP922Zn0dRFpC5XmQnbA30xtCrj8DxHkaiwzxmKplRr2JkjdZdOWMcNww2x9dMI4M3VEiqVL7XRuUUKjCy2GCgZagiKYwRBaLGGI00CNZP8A "Python 3 – Try It Online") - Python `import regex`  
[Try it online!](https://tio.run/##RU3RSsQwEHzPV4QSaFY90fOtpfZA8M033zyFzbm1gdiWtEflSr@9ZhNBCDOz2ZnZoZ/Jjy05tylfvXn6op/3ouho1od8@9Co6wqvAmhdPx4fajAA@rgHgOvjXm354SZ76r8H6@gzg1Jdqruy6T3hqdXKSdtJZbvhPMFiG60usMzeTrRr@3Fag/m@/J/lruvDWWc7kpnStpFa@dsXnE4tjaEMQC75qz9TIfNVkhspzM8YuMhXkMpl64ZGIBqGgJGYk4jqTyZthEDBP8KEF1ccFxhGbjFxEziuUzRWs4stGIEDKREjnOEQW0ysiT2pKDWZXw "PowerShell – Try It Online") - .NET
This is a port of the above, with `\3?+` changed to `(?>\3?)` to allow the regex to work on .NET (which lacks possessive quantifiers), so it can support 6 different regex engines at once.
It is not supported by Boost, which lacks both forward-declared and nested backreferences. It might not be possible for a single regex to work on all 7 engines.
[Answer]
# [Retina](https://github.com/mbuettner/retina), 22 bytes
Another shorter answer in the same language just came...
```
^(a)+(?<-1>b)+(?(1)c)$
```
[Try it online!](http://retina.tryitonline.net/#code=XihhKSsoPzwtMT5iKSsoPygxKWMpJA&input=YWFiYg)
This is a showcase of the balancing groups in regex, which is [explained fully by Martin Ender](https://stackoverflow.com/a/17004406/6211883).
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.
[Answer]
# Befunge-93, 67 bytes
```
0v@.<  0<@.!-$<  >0\v
+>~:0`!#^_:"a" -#^_$ 1
~+1_^#!-"b" _ ^#`0: <
```
[Try it here!](http://www.quirkster.com/iano/js/befunge.html) Might explain how it works later. Might also try to golf it just a tad bit more, just for kicks.
[Answer]
## 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.
[Answer]
# 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!
[Answer]
# [Nekomata](https://github.com/AlephAlpha/Nekomata) + `-e`, 3 bytes
```
N;<
```
[Attempt This Online!](https://ato.pxeger.com/run?1=m70iLzU7PzexJHFNtJJurpKOgpJuqlLsgqWlJWm6Fov9rG2WFCclF0P5C26-U0pMUuJSSkxMglBAGsoAsWBMMBvOgfBAXJAIEENkQAwwAVUIMRZEgoUhNiRB1YHZUOUwg6EOgOiDaEmEUhBjYOZADYKYBDEKoiEJagnUFpg1MHuSlCDeBgA)
```
N;<
N       Check nonempty
 ;      Split the list into two parts
  <     Check elementwise less than; fails if their lengths are different
```
[Answer]
# [MATL](https://github.com/lmendo/MATL), 9 bytes
```
vHI$e!d1=
```
[**Try it online!**](http://matl.tryitonline.net/#code=dkhJJGUhZDE9&input=J2FhYWJiYic)
The output array is truthy if it is non-empty and all its entries are nonzero. Otherwise it's falsy. Here are [some examples](http://matl.tryitonline.net/#code=YCAgICAgICAgICAgICUgaW5maW5pdGUgbG9vcCB0byB0YWtlIGFsbCBpbnB1dHMKPyd0cnV0aHknICAgICUgaWY6IHRydXRoeQp9J2ZhbHN5JyAgICAgJSBlbHNlOiBmYWxzeQpdICAgICAgICAgICAgJSBlbmQgaWYKRFQgICAgICAgICAgICUgZGlzcGxheSBhbmQgZW5kIGxvb3A&input=W10KWzAgMSAyXQpbMyA0IC01XQpbMSAxOyAxIDFd).
```
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
```
[Answer]
# 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 `b`s 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
```
[Answer]
# Ruby, 24 bytes
```
eval(gets.tr'ab','[]')*1
```
(This is just [xnor's brilliant idea](https://codegolf.stackexchange.com/a/86032/4372) in Ruby form. [My other answer](https://codegolf.stackexchange.com/a/86184/4372) 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.
[Answer]
# 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
```
[Answer]
# JavaScript, ~~44~~ 42
[Crossed out 44 is still regular 44 ;(](http://meta.codegolf.stackexchange.com/a/7427/7796)
```
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)
```
[Answer]
# ANTLR, 31 bytes
```
grammar A;r:'ab'|'a'r'b'|r'\n';
```
Uses the same concept as @dmckee's [YACC answer](https://codegolf.stackexchange.com/a/86049/56755), just slightly more golfed.
To test, follow the steps in ANTLR's [Getting Started tutorial](https://github.com/antlr/antlr4/blob/master/doc/getting-started.md). 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>, '
'}
```
[Answer]
## R, ~~64~~ ~~61~~ 55 bytes, ~~73~~ 67 bytes (robust) or 46 bytes (if empty strings are allowed)
1. Again, [xnor's answer](https://codegolf.stackexchange.com/a/86032/49439) reworked. If it is implied by the rules that the input will consist of a string of `a`s and `b`s, 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.
[Answer]
# [Japt](https://github.com/ETHproductions/japt), 11 bytes
```
©¬n eÈ¦Ug~Y
```
[Try it online!](https://ethproductions.github.io/japt/?v=2.0a0&code=qaxuIGXIplVnflk=&input=LW1SIFsKImFiIiwKImFhYmIiLAoiYWFhYmJiIiwKImFhYWFiYmJiIiwKImFhYWFhYmJiYmIiLAoiYWFhYWFhYmJiYmJiIiwKCiIiLAoiYSIsCiJiIiwKImFhIiwKImJhIiwKImJiIiwKImFhYSIsCiJhYWIiLAoiYWJhIiwKImFiYiIsCiJiYWEiLAoiYmFiIiwKImJiYSIsCiJiYmIiLAoiYWFhYSIsCiJhYWFiIiwKImFhYmEiLAoiYWJhYSIsCiJhYmFiIiwKImFiYmEiLAoiYWJiYiIsCiJiYWFhIiwKImJhYWIiLAoiYmFiYSIsCiJiYWJiIiwKImJiYWEiLAoiYmJhYiIsCiJiYmJhIiwKImJiYmIiLApd)
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](https://codegolf.stackexchange.com/a/86037/78410).
[Answer]
# [Prolog (SWI)](http://www.swi-prolog.org), ~~34~~ 33 bytes
```
-[].
-L:-append([97|M],`b`,L),-M.
```
[Try it online!](https://tio.run/##ZZDBCsMgEETv@YoeFdxcS9NDfyCB3ENApbYEJBGT4qX/bpuWgju9OW9dZ8YQF7/caU1TzjSMdUVtQyYEN1/FcDo@u1Fpq1UrFXV1TqKXDfUqxWlzfhZbfDh5/qmb8auTdXWhQxKkjdWFMJbLtwawE0Qf9ge/tMTljeLMN8sBE2DAY5eKrfFGFt5nM7DDQvAx3J9bGpA8HuaDgDwhj8iNLJSDdlgP@@3T/AI "Prolog (SWI) – Try It Online")
[Answer]
# [Brachylog (newer)](https://github.com/JCumin/Brachylog), ~~11~~ ~~10~~ 6 bytes
```
o?ḅĊlᵛ
```
[Try it online!](https://tio.run/##SypKTM6ozMlPN/pfXa6koGunoFRuX/2obcOjpuZHHcuVSopKU/WUakDMtMScYiC79uGuztqHWyf8z7d/uKP1SFfOw62z//@PVkpMUtJRSkxMglBAGsoAsWBMMBvOgfBAXJAIEENkQAwwAVUIMRZEgoUhNiRB1YHZUOUwg6EOgOiDaEmEUhBjYOZADYKYBDEKoiEJagnUFpg1MHuSlGIB "Brachylog – 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.
```
]