| Bytes | Lang | Time | Link |
|---|---|---|---|
| 073 | Setanta 0.10.4 | 240728T230639Z | bb94 |
| 063 | Turing Machine 2 tapes | 240728T165556Z | z.. |
| 080 | TypeScript’s type system | 231215T181001Z | noodle p |
| 003 | Nekomata + e | 230607T074304Z | alephalp |
| 010 | Thunno 2 | 230607T072728Z | The Thon |
| 023 | Knight v2 | 221119T021727Z | EasyasPi |
| 033 | Julia | 221118T214606Z | Ashlin H |
| 015 | J | 160720T200330Z | Conor O& |
| 003 | The purpose of this post is to demonstrate and explain the full list of golfed pure regexes that solve this challenge | 220707T074001Z | Deadcode |
| 004 | Vyxal | 220707T202531Z | Deadcode |
| 020 | APL | 220711T035410Z | Vadim Tu |
| nan | 220710T224548Z | bigyihsu | |
| 010 | BQN | 220707T164736Z | DLosc |
| 032 | Python 3 | 160720T235602Z | xnor |
| 037 | Java 8 | 160721T071939Z | Kevin Cr |
| 046 | Lua | 220707T085028Z | Luatic |
| 023 | sed | 220707T075021Z | Sisyphus |
| 040 | Python 2 | 160720T194629Z | KarlKast |
| 007 | Vyxal | 220706T200657Z | naffetS |
| 024 | Curry PAKCS | 220425T021000Z | alephalp |
| 011 | J | 220222T121638Z | sinvec |
| 083 | Shue | 220216T211305Z | AnttiP |
| 088 | Clojure | 200508T184713Z | Bob Jarv |
| 006 | NST | 200416T140337Z | user9206 |
| 8178 | SNOBOL4 CSNOBOL4 | 190226T171745Z | Giuseppe |
| 041 | shortC | 200417T174610Z | Wezl |
| 006 | 05AB1E | 200417T104634Z | Kevin Cr |
| 014 | Keg | 200216T091355Z | lyxal |
| 013 | /// | 200209T184607Z | EdgyNerd |
| 021 | Burlesque | 200209T105944Z | DeathInc |
| 064 | Unix TMG | 200209T070526Z | Andriy M |
| 020 | GolfScript | 200123T030920Z | user8505 |
| 025 | Perl 6 | 190321T033153Z | Jo King |
| 135 | C# .NET | 190819T235350Z | canttalk |
| nan | brainfuck and bfasm | 190818T115231Z | Kamila S |
| nan | 190321T025802Z | GammaFun | |
| 085 | C | 190323T210121Z | qookie |
| 008 | Stax | 190322T211516Z | recursiv |
| 042 | Python 2 | 190322T182017Z | Chas Bro |
| 054 | C# Visual C# Interactive Compiler | 190321T161613Z | dana |
| 1716 | Ruby | 190322T080029Z | G B |
| 039 | PowerShell | 190322T042906Z | mazzy |
| 046 | APLNARS | 190321T085812Z | user5898 |
| 033 | Perl 6 | 190321T015849Z | bb94 |
| 006 | Brachylog newer | 190301T070950Z | Unrelate |
| 026 | Gol><> | 190226T180027Z | KrystosT |
| 037 | Python 2.7 | 180601T161721Z | Khalil |
| 050 | Batch | 180530T014950Z | l4m2 |
| 033 | Prolog SWI | 180529T062158Z | ASCII-on |
| 038 | SmileBASIC 3 | 180529T224427Z | snail_ |
| 011 | Japt | 180529T045926Z | Bubbler |
| 060 | Cubically | 170807T143852Z | Kamil Dr |
| 037 | Lua | 170806T221032Z | tehtmi |
| 6746 | R | 160722T152022Z | Andre |
| 4147 | /// | 170804T105837Z | boboquac |
| 053 | awk | 161228T141728Z | James Br |
| 052 | Clojure | 161228T100121Z | NikoNyrh |
| 077 | Brainfuck | 161121T012344Z | Mitch Sc |
| 065 | C | 160720T225112Z | Stefano |
| 079 | R | 160806T002021Z | user5957 |
| 039 | Thue | 160801T213036Z | MegaTom |
| 050 | Bash | 160731T170428Z | Master_e |
| 053 | C | 160721T190923Z | Jasmes |
| 049 | Perl 6 | 160731T164527Z | lynn |
| 010 | K | 160731T130116Z | geocar |
| 007 | Pyth | 160730T235920Z | Anders K |
| 021 | K | 160730T223239Z | Chromozo |
| 052 | ><> | 160730T221057Z | owacoder |
| 069 | C | 160720T202230Z | Josh |
| 042 | Ruby | 160728T180834Z | Sherlock |
| 035 | TIBasic | 160728T162748Z | Timtech |
| 067 | Matlab | 160728T160919Z | sintax |
| 031 | ANTLR | 160728T145341Z | Copper |
| 031 | PHP bounty version | 160725T142513Z | Titus |
| 042 | JavaScript | 160721T190925Z | apsiller |
| 012 | Grime | 160720T193714Z | Zgarb |
| 029 | Bison/YACC 60 or | 160721T045549Z | dmckee - |
| 021 | k | 160723T114448Z | skeevey |
| 040 | PHP | 160723T020122Z | Titus |
| nan | Sed | 160722T220053Z | someonew |
| 101 | Python | 160722T175519Z | greyShif |
| 055 | Excel | 160722T061534Z | Joffan |
| 067 | C# | 160722T130308Z | Dion Wil |
| 031 | Ruby | 160721T193345Z | daniero |
| 014 | Actually | 160722T054108Z | user4594 |
| 034 | JavaScript | 160721T212722Z | Yay295 |
| 091 | Racket | 160721T224332Z | Steven H |
| 024 | Ruby | 160721T214401Z | daniero |
| 027 | x86 machine code | 160721T195546Z | anatolyg |
| 054 | Mathematica | 160721T062241Z | martin |
| 006 | Jelly | 160721T002810Z | Dennis |
| 004 | MATL | 160721T004706Z | Dennis |
| 019 | Brachylog | 160720T200014Z | Fatalize |
| 045 | Mathematica | 160721T094541Z | Martin E |
| 033 | Ruby | 160721T084222Z | Value In |
| 009 | MATL | 160720T211714Z | Luis Men |
| 028 | Octave | 160720T235128Z | Luis Men |
| 031 | Haskell | 160720T230805Z | xnor |
| 067 | Befunge93 | 160720T213717Z | user5585 |
| 039 | Haskell | 160720T212125Z | nimi |
| 010 | Pyke | 160720T205447Z | Blue |
| 013 | Pyth | 160720T202219Z | Cowabung |
| 052 | PowerShell v2+ | 160720T200513Z | AdmBorkB |
| 009 | 05AB1E | 160720T194547Z | Adnan |
| 044 | JavaScript | 160720T194847Z | Scimonst |
| 012 | Retina | 160720T194408Z | Martin E |
| 017 | Perl 5.10 | 160720T195612Z | Sake |
| 133 | Batch | 160720T200312Z | Neil |
| 022 | Retina | 160720T194436Z | Leaky Nu |
| 075 | C Ansi | 160720T193934Z | dj0wns |
Setanta 0.10.4, 72 73 bytes
+1 byte to handle the empty case
For odd-length strings, n will be a non-integer, so s[i+n] tries to access a character at a non-integer index. This returns undefined, which cannot be displayed in Setanta but can be manipulated, comparing unequal to any string and thus handling the odd-length case without an explicit check.
gniomh(s){n:=fad@s/2v:=n le i idir(0,n)v=v&s[i]=='a'&s[i+n]=='b'toradh v}
Turing Machine (2 tapes), 63 bytes
a a _ a _ a > >
a b _ b * * - <
b b a b * * > <
b _ _ c * * - -
Transitions are in the format:
[cur_state] [read1] [read2] [next_state] [write1] [write2] [>|-|<] [>|-|<]
initial state: a, final state: c
Demo
TypeScript’s type system, 80 bytes
type F<S>=S extends`a${infer A}b${infer B}`?B extends`a${any}`?B:F<`${A}${B}`>:S
Try it at the TS playground! Returns falsey (empty string) if there is an equal number of As and Bs, non-empty string otherwise.
This is a generic type F<S> which takes a string type and recursively removes a leading a and the first b, unless there’s an a after the first b.
This is the kind of challenge where TS types can really be competitive with actual programming languages!
Nekomata + -e, 3 bytes
N;<
N;<
N Check nonempty
; Split the list into two parts
< Check elementwise less than; fails if their lengths are different
Thunno 2, 10 bytes
Ṡ=s`abdcạ&
Explanation
Ṡ=s`abdcạ& # Implicit input
Ṡ= # Is the input sorted?
s # Swap so the input is back on top
`ab # Push the string "ab"
dc # Count the occurrences of "a" and "b"
ạ # Are they equal to each other?
& # Logical AND
# Implicit output
Knight (v2), 23 bytes
O&=l/L=xP2?x+*"a"l*"b"l
OUTPUT( # Output...
& # the first value...
: = half_len # which is assigning the value of
: / # the floored quotient of
: LENGTH( # - the length of
: = str PROMPT() # - the line from stdin, assigned to str
)
: 2 # - and 2
# ... if it is falsy, or...
: ? # whether the following values are equal:
: str # - str
: + # - concatenated:
: * "a" half_len # - "a" repeated half_len times
: * "b" half_len # - "b" repeated half_len times
)
It is the simple approach for languages with string multiplication, which first tests the length, then compares it to "a" * len(str) // 2 + "b" * len(str) // 2.
The code will output either true for true, or either 0 or false for false.
Julia, 33 bytes
^ =count
!s='a'^s=='b'^s>"ba"^s<1
The dyadic operator ^ is assigned to count, so count(x,y) becomes x^y. Alternatively, the operator ~ wouldn't require a space in the assignment statement due to its low precedence. In fact, ~ is evaluated after comparisons, making it a poor choice for this solution, which relies on multiple comparisons to ensure that the input has:
- an equal (non-zero) number of
'a'and'b', and - no occurrence of
"ba".
J, 17 15 bytes
-2 bytes thanks to 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, 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.
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 / Pythonregex), 11 bytes
^(a(?1)?b)$
Try it online! - Perl
Try it online! - PCRE1
Try it online! - PCRE2
Try it online! - Boost
Try it online! - Python import regex
Included for completeness. Already used in:
^ # 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! - PCRE1
Try it online! - PCRE2
Try it online! - Ruby
Included for completeness. Already used in G B's Ruby answer.
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! - Perl
Try it online! - PCRE1
Try it online! - PCRE2
Try it online! - Java
Turned out to be used in Kevin Cruijssen's Java answer, 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)^)
Included for completeness. Already used in:
- Leaky Nun's Retina answer
- AdmBorkBork's PowerShell answer
- Dion Williams's C# answer (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! - Perl
Try it online! - PCRE1
Try it online! - PCRE2
Try it online! - Java
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 / Pythonregex), 29 bytes
^(a(?=a*(?=(\3?+b))(\2)))+\2$
Try it online! - Perl
Try it online! - PCRE1
Try it online! - PCRE2
Try it online! - Java
Try it online! - Ruby
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 / Pythonregex / .NET), 32 bytes
^(a(?=a*(?=((?>\3?)b))(\2)))+\2$
Try it online! - Perl
Try it online! - PCRE1
Try it online! - PCRE2
Try it online! - Java
Try it online! - Ruby
Try it online! - Python import regex
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.
Vyxal, 7 6 5 4 bytes
I÷<g
Try it Online!
Try it Online! - 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!
Try it Online! - 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, 6 5 4 bytes
sṘ꘍g
Try it Online!
Try it Online! - 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, 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!
Try it Online! - 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, 5 bytes
fI÷<g
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
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÷‹⁼
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, 5 bytes
AḂs꘍↓
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 and MATL answer (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
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)
APL, 20 bytes
{⍵≡∊'ab'⍴⍨¨1⌈⌊2÷⍨≢⍵}
Naive approach: build the correct string of the same length, then compare.
Go, 126 bytes
func f(s string)bool{l:=len(s)-1
if l<1{return false}
x,y:=s[0]==97,s[l]==98
if l<2&&x&&y{return true}
return x&&y&&f(s[1:l])}
Recursive function, input is a string and returns a boolean. This checks the first and last characters, and recurses on the middle string.
Ungolfed:
func f(s string) bool {
l := len(s)
if l<2 {
return false
}
x, y := s[0]=='a', s[l-1]=='b'
if l==2 && x && y {
return true
}
return x && y && f(s[1:l-1])
}
BQN, 12 10 bytes
(¬≡∨)-⟜⊑⎊≢
Anonymous tacit function; takes a string and returns 0 for falsey, 1 for truthy. Try it here!
Explanation
(¬≡∨)-⟜⊑⎊≢
⊑ Get the first character of the string
-⟜ Subtract it from each character of the string
(where 'a'-'a' is 0, 'b'-'a' is 1, etc.)
⎊ If that errored because the string is empty,
≢ use the string's shape instead: an array containing a single 0
( ) Apply this function to that list of 0's and 1's:
∨ Sort in descending order
≡ Is the result identical to
¬ logically negating each?
If so, we have some number of 0's followed by an equal number of 1's
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.
Try it online! (Python 2, 33 bytes)
Java 8, 69 37 bytes
s->s.matches("(a(?=a*(\\2?+b)))+\\2")
Regex shamelessly 'borrowed' from here.
-6 bytes thanks to @Deadcode, plus a bit more by converting Java 7 to 8
Explanation:
s-> // Method with String parameters and boolean return-type
s.matches("...") // Check if the String matches the regex explained below
Regex explanation:
^ $ # (implicit by String#matches: match entire String)
+ # Repeat one or more times:
( ) # Capture group 1, which does:
a # Match an 'a'
(?= ) # With a positive look-ahead to:
a* # 0 or more 'a's
( ) # Followed by, in capture group 2:
\2 # The value of capture group 2,
?+ # zero or one times, giving prio to one, without backtracking
b # Following by a 'b'
\2 # Followed by the value of capture group 2 (the 'b's)
sed, 23 bytes
:0
s/a1*b/1/
t0
/^1$/!d
Repeatedly replace the anything of the form a1*b with 1, then check if the output contains a single 1.
Python 2, 43 40 Bytes
lambda s:''<s==len(s)/2*"a"+len(s)/2*"b"
Try it online! - considered 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
Shue, 83 bytes
y
n
a=ay
b=yb
ayb=y
=L
=R
ayR=yR
Lyb=Ly
ayR=n
Lyb=n
ba=#
#a=#
#b=#
a#=#
b#=#
#=n
=n
Outputs y for yes and n for no
Clojure, 88 bytes
(defn a[s](let[g(re-find #"^(a+)(b+)$"s)](and(not(nil? g))(=(count(g 1))(count(g 2))))))
Ungolfed version:
(defn ab?[s]
(let [ groups (re-find #"^(a+)(b+)$" s) ]
(and (not (nil? groups))
(= (count (groups 1)) (count (groups 2))))))
NST, 6 bytes
You need to enclose the input in brackets, e.g. ["ab"].
ab"Ṅ*§
Explanation
"ab" Define the string "ab".
Ṅ* Multiply this string by the natural number set.
The natural number set is [1, 2, 3, 4, 5, ...]
Since in NST a string is technically a set,
this yields the output
["ab", "aabb", "aaabbb", ...]
instead.
§ Does the (implicit) input belong to this set?
(Implicit input goes ahead of the operand.)
SNOBOL4 (CSNOBOL4), 81 78 bytes
INPUT POS(0) SPAN('A') @X REM . Y :F(END)
OUTPUT =IDENT(Y,DUPL('B',X)) 1
END
Match 'A's starting at beginning of string and set length to X. If the REMainder of the string is the same as X 'B's then output 1 else output nothing.
shortC, 41 bytes
AIa,b;K"%*[a]%n%*[b]%n",&a,&b);T++b-2*a+G
C (gcc), 69 bytes
main(){int a,b;scanf("%*[a]%n%*[b]%n",&a,&b);return 2*a/b+getchar();}
returns 0 if correct. I think I made it very hard to read when debugging, here is explanation:
int main(){
int a,b;
scanf("%*[a]%n%*[b]%n",&a,&b); // skips As, assigns count to a, skips Bs, assigns total to b
return 2*a/b // checks to make sure As and Bs are equal. Should give 1 (a/b = 1 if a=b)
+getchar(); // adds return of getchar, EOF if no trailing chars so checks for possibilities like abab
} // they add together to make 0, which is normally an "all clear" exit code
second post!
05AB1E, 6 bytes
ÇÂs{αß
Only 1 is truthy in 05AB1E, and it'll output 0 (or "" for the empty string) as falsey.
Try it online or verify all test cases.
Explanation:
Ç # Convert the (implicit) input-string to a list of integer codepoints
# i.e. "aaabbb" → [97,97,97,98,98,98]
# i.e. "baba" → [98,97,98,97]
# i.e. "aab" → [97,97,98]
# i.e. "" → []
 # Bifurcate this list (short for Duplicate & Reverse copy)
# STACK: [[97,97,97,98,98,98], [98,98,98,97,97,97]]
# STACK: [[98,97,98,97], [97,98,97,98]]
# STACK: [[97,97,98], [98,97,97]]
# STACK: [[], []]
s # Swap to get the duplicated list
# STACK: [[98,98,98,97,97,97], [97,97,97,98,98,98]]
# STACK: [[97,98,97,98], [98,97,98,97]]
# STACK: [[98,97,97], [97,97,98]]
# STACK: [[], []]
{ # Sort it
# STACK: [[98,98,98,97,97,97], [97,97,97,98,98,98]]
# STACK: [[97,98,97,98], [97,97,98,98]]
# STACK: [[98,97,97], [97,97,98]]
# STACK: [[], []]
α # Take the absolute difference at the same positions
# STACK: [[1,1,1,1,1,1]]
# STACK: [[0,1,1,0]]
# STACK: [[1,0,1]]
# STACK: [[], []]
ß # And take the minimum, which will be 1 if all were truthy;
# 0 if any were falsey; or an empty string if the list is empty
# STACK: [1]
# STACK: [0]
# STACK: [0]
# STACK: [""]
# (after which it is output implicitly as result)
///, 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.
Burlesque, 21 bytes
Jsojgwsa2==j)-]sm&&&&
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
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.
Perl 6, 25 bytes
{$_&&try !TR/ab/()/.EVAL}
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.
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);}}
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.
+>+[<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>>--[----->+<]>-----<<<<<]>+<<+<<[>>->+<<<-]>>>[<<<+>>>-]<[->+<<[>>>-<<+<-]>[<+>-]>>[<->[-]]<[<<<+>>>-]<]<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>,>>>>+++<<<<<<+>>[<<[-]<+>>>-]<<<[>>>+<<<-]>[<<<[-]>[-]>>>>>>>>[<<<<<<<<+>+>>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>[-]]>>>>>>[-]<<<<<<]<<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>[<<+>>-]+>>>[<<<<<-<+>>>>>>-]<<<<<<[>>>>>>+<<<<<<-]>[>>-<<[-]]>>>>>>++<<<<[<<<+>+>>-]<<<[>>>+<<<-]>[<<<[-]>[-]>>>>>>>>[<<<<<<<<+>+>>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>[-]]>>>>>>[-]<<<<<<]<<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>>+<-<<<]>++<<+<<[>>->+<<<-]>>>[<<<+>>>-]<[->+<<[>>>-<<+<-]>[<+>-]>>[<->[-]]<[<<<+>>>-]<]>>[-]<<<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>+>>>+<<<<<<<<<[-]>[-]>>>>>>>>[<<<<<<<<+>+>>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>>>>>>>[-]<<<<<<]>+++<<+<<[>>->+<<<-]>>>[<<<+>>>-]<[->+<<[>>>-<<+<-]>[<+>-]>>[<->[-]]<[<<<+>>>-]<]>>[-]<<<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>[<<<+>>>-]+>[<<<<-<+>>>>>-]<<<<<[>>>>>+<<<<<-]>[>>>-<<<[-]]>>>.<<<]<<<[>>+>+<<<-]>>[<<+>>-]>[[-]<<<[-]>[-]>>]<<]
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 givesunknown file attribute:if run directly.- Empty case:
${1:?}handles exactly this.
Zsh, 29 bytes
eval \(${${1//a/(+}//b/+i)}\)
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.
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;
}
Stax, 8 bytes
é«<òαøòâ
It compares the input with "ab" having its characters repeated inputLength / 2 times.
C# (Visual C# Interactive Compiler), 54 bytes
x=>x!=""&!x.OrderBy(y=>-y).Where((y,i)=>y==x[i]).Any()
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()
PowerShell, 39 bytes
$args-in($args|% t*y|%{($r="a$r"+'b')})
PowerShell 5.1, 37 bytes
$args-in($args|% t*y|%{($r="a$r`b")})
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
Perl 6 (33 bytes)
{?/^(a+)(b+)$/&&$0.ords==$1.ords}
Brachylog (newer), 11 10 6 bytes
o?ḅĊlᵛ
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.
Gol><>, 26 bytes
&TiE!tlF:`a=Q&P&~{|}|l&-zh
Wow, five minutes and it is already smaller, 4 bytes knocked off!
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
Python 2.7, 37 bytes
lambda s:s.count('a')==s.count('b')>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.
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
Japt, 11 bytes
©¬n eȦUg~Y
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.
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
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.
Lua, 37 bytes
Works with Lua 5.1, Lua 5.2, and Lua 5.3.
os.exit((...):match"^%bab$":find"ba")
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.
R, 64 61 55 bytes, 73 67 bytes (robust) or 46 bytes (if empty strings are allowed)
Again, xnor's answer reworked. If it is implied by the rules that the input will consist of a string of
as andbs, 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)))If the input is not robust and may contain some garbage, e.g.
aa3bb, then the following version should be considered (must returnTRUEfor true test cases, not NULL):if(length(y<-scan(,'')))is.null(eval(parse(t=chartr("ab","{}",y))))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.
///, 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
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
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.
Brainfuck, 77 bytes
,
[
[
>+[>+<-]<<
,[>->+<<-]
>[<<]
>
]
>+[<<]
>
[
>-[>+<-]<<
,
[
[>->+<<-]
>[<<]
<
]
>>
]
+>[<]
]
<.
Expects input without a trailing newline. Outputs \x00 for false and \x01 for true.
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/.
C, 65 bytes
m,t;C(char*c){for(m=1,t=0;*c;)m>0&*c++-97&&(m-=2),t+=m;return!t;}
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.
Thue, 39 bytes
$::=:::
ab::=x
axb::=x
-x-::=~1
::=
-$-
Outputs a "1" for true and nothing for false.
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
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!
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.
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.
Pyth, 7 bytes
.AanV_S
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
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
><>, 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<
C, 69 bytes
69 bytes:
#define f(s)strlen(s)==2*strcspn(s,"b")&strrchr(s,97)+1==strchr(s,98)
For those unfamiliar:
strlendetermines the length of the stringstrcspnreturns the first index in string where the other string is foundstrchrreturns a pointer to the first occurrence of a characterstrrchrreturns a pointer to the last occurrence of a character
A big thanks to Titus!
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
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
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.
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>, '
'}
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
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)
Grime, 12 bytes
A=\aA?\b
e`A
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.
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.
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
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
1for 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);
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
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))
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.
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.
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?
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.
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)
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);}
});
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.
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.
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:
- If the counter is not 0 at the end, the string doesn't match
- 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
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*)
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.
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!
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.
Brachylog, 23 19 bytes
@2L,?lye:"ab"rz:jaL
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
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.
MATL, 9 bytes
vHI$e!d1=
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
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.
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.
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.
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.
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.
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
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.
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!.
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(''))
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 thebs in the string aren't balanced in the same way that(and)normally need to be, someaorbwill remain in the string, sinceba, orb;acan't be resolved and a singleaorbon its own can't either. To get rid of all theas and thebs there has to be one correspondingbto the right of eacha. - If the
aand thebaren't all nested (e.g. if we have something likeababoraabaabbb) then we'll end up with multiple;(and potentially someas andbs) because the first iteration will find multipleabs 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.)
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.
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.
Retina, 22 bytes
Another shorter answer in the same language just came...
^(a)+(?<-1>b)+(?(1)c)$
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.
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.
