Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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

definition

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

Challenge

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

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

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

  • Standard code golf rules apply.

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

Truthy test cases

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

Falsy test cases

""
"a"
"b"
"aa"
"ba"
"bb"
"aaa"
"aab"
"aba"
"abb"
"baa"
"bab"
"bba"
"bbb"
"aaaa"
"aaab"
"aaba"
"abaa"
"abab"
"abba"
"abbb"
"baaa"
"baab"
"baba"
"babb"
"bbaa"
"bbab"
"bbba"
"bbbb"
share|improve this question
    
"Your program cannot use any external computation tools , including network , external programs etc" is already in our standard loopholes. – Leaky Nun yesterday
17  
Can the input be empty? (You're saying it's not part of the language, but not whether it's an input we need to consider.) – Martin Ender yesterday
    
What if our language doesn't have truthy or falsy? Would empty string == truthy and non-empty string == falsy be acceptable? – Dr Green Eggs and Iron Man yesterday
1  
Nice challenge, but I think the title could be a little less ambiguous (i.e. a mention of a^n b^n or similar, rather than just the number of as equalling the number of bs) – Sp3000 yesterday
1  
@Sp3000 I choosed this title because it looked fun . I may change it later to sth else ... – GLASSIC yesterday

40 Answers 40

Python 2, 33 bytes

eval(input().translate(')('*128))

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).

share|improve this answer
25  
Ok, that's clever. – TLW yesterday

Retina, 12 bytes

Credits to FryAmTheEggman who found this solution independently.

+`a;?b
;
^;$

Prints 1 for valid input and 0 otherwise.

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

Explanation

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

Stage 1

+`a;?b
;

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

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

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

Stage 2:

^;$

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

share|improve this answer

MATL, 5 4 bytes

tSP-

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

Thanks to @LuisMendo for golfing off 1 byte!

Try it online!

How it works

t      Push a copy of the implicitly read input.
 S     Sort the copy.
  P    Reverse the sorted copy.
   -   Take the difference of the code point of the corresponding characters
       of the sorted string and the original.
share|improve this answer
1  
My second (working) MATL answer. :) – Dennis yesterday

Grime, 12 bytes

A=\aA?\b
e`A

Try it online!

Explanation

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

share|improve this answer
    
Why didn't you do it in J? – Leaky Nun yesterday
    
@LeakyNun I just wanted to show off Grime. :P – Zgarb yesterday
    
You built this language? – Leaky Nun yesterday
    
@LeakyNun Yes. Development is slow, but ongoing. – Zgarb yesterday

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!.

share|improve this answer
    
What happens with empty input? – TimmyD yesterday
2  
Look for non-zero in the post; it’s in there :) – Lynn yesterday
    
@Lynn Doesn't the spec only say no-zero for a valid language though? Not about input. – Emigna yesterday
    
True. Thought wrong there. But you can still do .M{J¹ÔQ0r for yours. – Emigna yesterday
    
@Emigna Thanks, I have edited the post. – Adnan yesterday

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.

share|improve this answer
    
This is lovely. I often forget how useful it is that Haskell orders the elements of a list comprehension in a consistent and very specific way. – Vectornaut 22 hours ago

Brachylog, 23 19 bytes

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

Try it online!

Explanation

@2L,                  Split the input in two, the list containing the two halves is L
    ?lye              Take a number I between 0 and the length of the input              
        :"ab"rz       Zip the string "ab" with that number, resulting in [["a":I]:["b":I]]
               :jaL   Apply juxtapose with that zip as input and L as output
                        i.e. "a" concatenated I times to itself makes the first string of L
                        and "b" concatenated I times to itself makes the second string of L
share|improve this answer
8  
Congratulations on getting on tryitonline.net! – Leaky Nun yesterday

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.
share|improve this answer

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

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

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

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

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

Try it here!

share|improve this answer
    
Closest I can manage including the non-empty test case is 18 bytes: $_&&=y/a//==y/b// (requires -p), without the empty you could drop the && for 16! So close... – Dom Hastings yesterday
    
So I can do another 17 bytes: echo -n 'aaabbb'|perl -pe '$_+=y/a//==y/b//' but I can't shift another byte... Might have to give up on this! – Dom Hastings 2 hours ago

J, 17 bytes

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

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

Old versions:

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

Proof and explanation

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

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

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

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

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

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

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

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

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

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

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

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

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

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

share|improve this answer
    
I modified it into 2&#-:'ab'#~# which should let you avoid the error and just output 0 instead while still using 12 bytes. – miles yesterday
    
@miles Fascinating! I never thought about it like that. – Cᴏɴᴏʀ O'Bʀɪᴇɴ yesterday
    
Does this handle the empty string? – Zgarb yesterday
    
@Zgarb fixed it! – Cᴏɴᴏʀ O'Bʀɪᴇɴ 22 hours ago

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(''))

share|improve this answer
    
The f= can be omitted. – Leaky Nun yesterday
    
Is a function expression a valid submission, or must it actually be, ahem, functional? – Scimonster yesterday
    
A function is a valid submission. – Leaky Nun yesterday
    
@TimmyD It used to return true, but now it returns false. – Scimonster yesterday
    
s.match will turn your string into a regexp for you. Also, I think using a template string might save you a couple of bytes. – Neil yesterday

Bison/YACC 28 bytes

(well, the compilation for a YACC program is a couple of steps so might want to include some for that)

%%
c : 'a' 'b' | 'a' c 'b' ;

I'm only positive that this code works because I haven't yet tried it: it doesn't want to run on my macbook. (I know, Knuth said it better. I agree.) 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.

share|improve this answer

Retina, 22 bytes

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

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

Try it online!

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

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

share|improve this answer

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.

share|improve this answer

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.

share|improve this answer
    
Won't this give false positives on strings like ba or abab? – Zgarb yesterday
    
Ahh yes, I misread the post since I could not see the picture since its blocked for me. Fixing it! – dj0wns yesterday

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.

share|improve this answer

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.

share|improve this answer

C, 62 bytes

62 bytes:

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

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
share|improve this answer

Python, 43 40 Bytes

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

connsidered the obvious solution thanks to Leaky Nun

other idea, 45 bytes:

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

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

now gives false for the empty string

-3 bytes thanks to xnor

share|improve this answer
    
Yes, lambdas don't have to be named. – Leaky Nun yesterday
    
lambda s:list(s)==sorted("ab"*len(s)//2) (Python 3) – Leaky Nun yesterday
    
lambda s:s=="a"*len(s)//2+"b"*len(s)//2 (Python 3) – Leaky Nun yesterday
    
yeah, I realized that while posting it. lol, the obvious solution is shorter in Python 2: – KarlKastor yesterday
    
lambda s:s=="a"*len(s)/2+"b"*len(s)/2 if you accept errors as falsey – Leaky Nun yesterday

Octave, 28 bytes

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

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

Try it at ideone.

Explanation

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

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

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

share|improve this answer

MATL, 9 bytes

vHI$e!d1=

Try it online!

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

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

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.

share|improve this answer

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*)
share|improve this answer
1  
It's probably shortest with a recursive regex: #~StringMatchQ~RegularExpression@"(a(?1)?b)"& – Martin Ender yesterday
    
@MartinEnder Ah yes - much better - I'll delete & let you post that, since it doesn't resemble my awful attemp in the slightest! – martin yesterday
1  
No, don't delete yours. A regex-less solution is still interesting. :) – Martin Ender yesterday

JavaScript, 44

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

Works by recursively stripping off the outer a and b. When there's not a match on ^aa+b+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)
share|improve this 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 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
share|improve this answer

Ruby, 33 bytes

Try it online

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

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);}
});

share|improve this answer

Ruby, 31 bytes

Aw, that poor syntax highlighter :)

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

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

test here

share|improve this answer

C, 65 64 bytes

m,t;C(char*c){for(m=1,t=0;*c;)m>0&*c++-97&&m----,t+=m;return!t;}
share|improve this answer

C, 57 Bytes

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

Try it on Ideone

share|improve this answer
    
Since I'm new here and can't comment on other answers yet, I just want to point out that 62b solution from @Josh gives false positive on strings like "aaabab". – Jasmes 2 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.