28
\$\begingroup\$

If you express some positive integer in binary with no leading zeros and replace every 1 with a ( and every 0 with a ), then will all the parentheses match?

In most cases they won't. For example, 9 is 1001 in binary, which becomes ())(, where only the first two parentheses match.

But sometimes they will match. For example, 44 is 101100 in binary, which becomes ()(()), where all the left parentheses have a matching right parenthesis.

Write a program or function that takes in a positive base ten integer and prints or returns a truthy value if the binary-parentheses version of the number has all matching parentheses. If it doesn't, print or return a falsy value.

The shortest code in bytes wins.

Related OEIS sequence.

Truthy examples below 100:

2, 10, 12, 42, 44, 50, 52, 56

Falsy examples below 100:

1, 3, 4, 5, 6, 7, 8, 9, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 45, 46, 47, 48, 49, 51, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
\$\endgroup\$
  • 5
    \$\begingroup\$ More OEIS \$\endgroup\$ – Mego Nov 16 '15 at 3:44
  • 10
    \$\begingroup\$ There's a sequence for everything... \$\endgroup\$ – Arcturus Nov 16 '15 at 4:38

26 Answers 26

8
\$\begingroup\$

TeaScript, 9 bytes 16 18 20 22 24

Saved 2 bytes thanks to @ETHproductions

!x÷W(n,¢)

Woah. That's short. Uses @xnor's approach. This will use the recursive replace function (W) which will replace all 10 equal to () with nothing. If the string is blank it is balanced.


Using a version of TeaScript made after this challenge was posted this could become 7 bytes:

!x÷W(n)

Ungolfed

!xT(2)W(n,``)

Explanation

!      // NOT, returns true if empty string, else false
 xT(2)   // To binary
 W(n,``) // n is 10, reclusive replaces 10 or (), with nothing.
\$\endgroup\$
  • 1
    \$\begingroup\$ Excellent! Two things that might help: 1) If it's falsy when going up, it's already been falsy going down, so you shouldn't need the first tilde. 2) I believe ~--c is falsy in exactly the same scenario as c--. \$\endgroup\$ – ETHproductions Nov 16 '15 at 15:27
  • \$\begingroup\$ @ETHproductions awesome, thanks! Now I'm down to 16 bytes \$\endgroup\$ – Downgoat Nov 16 '15 at 15:32
13
\$\begingroup\$

Pyth, 10 bytes

!uscG`T.BQ

Try this test suite in the Pyth Compiler.

How it works

              (implicit) Store the evaluated input in Q.
       .BQ    Return the binary string representation of Q.
 u            Reduce w/base case; set G to .BQ and begin a loop:
     `T         Return str(10) = "10".
   cG           Split G (looping variable) at occurrences of "10".
  s             Join the pieces without separators.
              Set G to the returned string.
              If the value of G changed, repeat the loop.
              This will eventually result in either an empty string or a
              non-empty string without occurrences of "10".
!             Return (and print) the logical NOT of the resulting string.
\$\endgroup\$
  • \$\begingroup\$ I came up with the equivalent !u:G`Tk.BQ. Arguably easier to understand. \$\endgroup\$ – orlp Nov 16 '15 at 3:57
  • \$\begingroup\$ Yes, that's certainly a more natural choice. \$\endgroup\$ – Dennis Nov 16 '15 at 4:08
8
\$\begingroup\$

Python2, 87 bytes

try:exec"print 1,"+"".join(["],","["][int(c)]for c in bin(input())[2:])
except:print 0

A terrible implementation that abuses syntax errors.

\$\endgroup\$
  • 3
    \$\begingroup\$ This is code golf. Terrible is a compliment. \$\endgroup\$ – corsiKa Nov 17 '15 at 23:06
8
\$\begingroup\$

JavaScript (ES6), 55 54 51 bytes

n=>![...n.toString(d=2)].some(c=>(d+=c*2-1)<2)*d==2

Saved bytes thanks to @Vɪʜᴀɴ and @xsot!

Explanation

n=>
  ![...n.toString(    // convert the input to an array of binary digits
    d=2)]             // d = current depth (+2)
      .some(c=>       // iterate through the digits
        (d+=c*2-1)    // increment or decrement the parenthesis depth
          <2          // if the depth goes negative, return false
      )*
        d==2          // if we finished at a depth of 0, return true
\$\endgroup\$
  • 1
    \$\begingroup\$ You can save two bytes by removing the not needed f=. You can also use use +c instead of c|0 to case to an integer. You can also use (+c?d++:d--) which is even shorter \$\endgroup\$ – Downgoat Nov 16 '15 at 4:15
  • \$\begingroup\$ @Vɪʜᴀɴ OK. Is there some kind of guide as to when I need to use f=? Because a lot of other JavaScript answers on the site name their functions. \$\endgroup\$ – user81655 Nov 16 '15 at 4:19
  • 1
    \$\begingroup\$ Typically you only need to give the function a name if the challenge requires you to do so. Otherwise it's safe to assume that unnamed functions are fine. \$\endgroup\$ – Alex A. Nov 16 '15 at 4:20
  • \$\begingroup\$ In Firefox, running this for 11, returns true when it should return false \$\endgroup\$ – Downgoat Nov 16 '15 at 4:25
  • 2
    \$\begingroup\$ I don't know javascript, but I attempted to cut a few bytes and it works in chrome: n=>![...n.toString(d=2)].some(c=>(d+=c*2-1)<2)*d==2 \$\endgroup\$ – xsot Nov 16 '15 at 9:45
7
\$\begingroup\$

Python 2, 45 bytes

f=lambda n,i=1:i*n>0<f(n/2,i+(-1)**n)or n<i<2

A recursive function. Reads binary digits of n from the end, keeping a count i of the current nesting level of the parens. If it falls below 0, reject. When we reach the start, checks whether the count is 0.

Actually, we start the count at i=1 to make it easy to check if it has fallen to 0. The only terminal success case is n==0 and i==1, checked with n<i<2. We force this check to happen if n==0, or if i falls to 0, in which case it automatically fails.

feersum saved two bytes by restructuring the non-recursive cases with inequalities to short-circuit.

\$\endgroup\$
  • 3
    \$\begingroup\$ Needs more conditional abuse. f=lambda n,i=1:n>0<i*f(n/2,i+(-1)**n) or n<i<2, at least, saves 1. \$\endgroup\$ – feersum Nov 16 '15 at 8:26
6
\$\begingroup\$

CJam, 11 bytes

ri2b"}{"f=~

This is a tad unclean: For parenthifiable numbers, it will print one or more blocks. For non-parenthifiable numbers, it will crash without printing anything to STDOUT. If you try this online in the CJam interpreter, keep in mind that it doesn't distinguish between STDOUT and STDERR.

Since non-empty/empty strings are truthy/falsy in CJam and printed output is always a string, it arguably complies with the rules. At the added cost of 3 more bytes, for a total of 14 bytes, we can actually leaves a truthy or falsy string on the stack that will be printed:

Lri2b"}{"f=~]s

This still crashes for non-parenthifiable numbers, which is allowed by default.

Test runs

$ cjam <(echo 'ri2b"}{"f=~') <<< 52 2>&-; echo
{{}{}}
$ cjam <(echo 'ri2b"}{"f=~') <<< 53 2>&-; echo

$ cjam <(echo 'ri2b"}{"f=~') <<< 54 2>&-; echo

$ cjam <(echo 'ri2b"}{"f=~') <<< 55 2>&-; echo

$ cjam <(echo 'ri2b"}{"f=~') <<< 56 2>&-; echo
{{{}}}

How it works

ri          e# Read an integer from STDIN.
  2b        e# Push the array of its binary digits.
    "}{"f=  e# Replace 0's with }'s and 1's with {'s.
          ~ e# Evaluate the resulting string.
            e# If the brackets match, this pushes one or more blocks.
            e# If the brackets do not match, the interpreter crashes.

CJam, 15 bytes

ri2bs_,{As/s}*!

Try this fiddle in the CJam interpreter or verify all test cases at once.

How it works

ri               Read an integer from STDIN.
  2b             Push the array of its binary digits.
    s            Cast to string.
     _,          Push the string's length.
       {    }*   Do that many times:
        As/        Split at occurrences of "10".
           s       Cast to string to flatten the array of strings.
              !  Push the logical NOT of the result.
\$\endgroup\$
  • 1
    \$\begingroup\$ darn, you barely beat me again.... \$\endgroup\$ – GamrCorps Nov 16 '15 at 3:38
6
\$\begingroup\$

Python, 51 bytes

lambda n:eval("'0b'==bin(n)"+".replace('10','')"*n)

An anonymous function. Evaluates to an expression that looks like

'0b'==bin(n).replace('10','').replace('10','').replace('10','')...

Each replacement removes all 10, which correspond to (). After all replacements have been made, the function returns whether what's left is just the binary prefix 0b. It more than suffices to make n replacements, since a k-digit number takes at most k/2 steps, and its value is most 2**k.

\$\endgroup\$
4
\$\begingroup\$

Ruby, 40

->i{n='%0b'%i;1while n.slice!'10';n<?0}

Simple string manipulation. Drops '10' until there is none left.

\$\endgroup\$
4
\$\begingroup\$

Seriously, 17 bytes

,;2@¡@`""9u$(Æ`nY

Outputs 0 for false and 1 for true. Try it online.

Explanation:

,      get value from stdin
;      dupe top of stack
2@¡    pop a: push a string containing the binary representation of a (swapping to get order of operands correct)
@      swap top two elements to get original input back on top
`""9u$(Æ` define a function:
  ""     push empty string
  9u$    push "10" (push 9, add 1, stringify)
  (      rotate stack right by 1
  Æ      pop a,b,c: push a.replace(b,c) (replace all occurrences of "10" in the binary string with "")
n      pop f,a: call f a times
Y      pop a: push boolean negation of a (1 if a is falsey else 0)
\$\endgroup\$
4
\$\begingroup\$

Japt, 23 bytes

Japt is a shortened version of JavaScript. Interpreter

Us2 a e@+X?++P:P-- &&!P

This reminds me just how far Japt has yet to go compared to TeaScript. After revamping the interpreter in the next few days, I'd like to add in "shortcut" chars like Vɪʜᴀɴ's.

How it works

       // Implicit: U = input number, P = empty string
Us2 a  // Convert U to base 2, then split the digits into an array.
e@     // Assert that every item X in this array returns truthily to:
 +X?   //  If X = 1,
 ++P   //   ++P. ++(empty string) returns 1.
 :P--  //  Otherwise, P--. Returns false if P is now -1.
&&!P   // Return the final result && !P (true if P is 0; false otherwise).
       // Implicit: output final expression

Shortly after this challenge, @Vɪʜᴀɴ (now known as @Downgoat) helped me implement a recursive-replace feature, like W in the TeaScript answer. This means that this challenge can now be done in just 5 bytes:

!¢eAs  // Implicit: U = input integer, A = 10
 ¢     // Convert U to binary.
  eAs  // Recursively remove instances of A.toString().
!      // Return the logical NOT of the result (true only for the empty string).

Test it online!

\$\endgroup\$
3
\$\begingroup\$

Mathematica, 49 bytes

(#~IntegerDigits~2//.{x___,1,0,y___}:>{x,y})=={}&
\$\endgroup\$
  • \$\begingroup\$ I can't read Mathematica. Explanation, please? :) \$\endgroup\$ – Conor O'Brien Nov 16 '15 at 15:44
  • \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ Convert the number into base 2 (as a list), then repeatedly remove 1,0 from the list, and test if the result is an empty list. \$\endgroup\$ – alephalpha Nov 16 '15 at 15:58
3
\$\begingroup\$

Octave, 48 bytes

@(a)~((b=cumsum(2*dec2bin(a)-97))(end)|any(b<0))
\$\endgroup\$
3
\$\begingroup\$

C++, 104 94 bytes

#include<iostream>
int n,c;int main(){for(std::cin>>n;n&c>=0;n>>=1)c+=n&1?-1:1;std::cout<<!c;}

Run with this compiler, must specify standard input before running.

Explanation

  • Declarations outside of main initialize to 0.
  • Reading a decimal implicitly converts to binary, because this is a computer.
  • We check bits/parenthesis right to left because of n>>=1.
  • c+=n&1?-1:1 keeps count of open parenthesis ).
  • n&c>=0 stops when only leading 0s remain or parenthesis close more than they open.
\$\endgroup\$
3
\$\begingroup\$

Haskell, 49 46 bytes

0#l=l==1
_#0=2<1
n#l=div n 2#(l+(-1)^n)
f=(#1)

Usage example: f 13 -> False.

I'm keeping track of the nesting level l like many other answers. However, the "balanced" case is represented by 1, so the "more-)-than-(" case is 0.

PS: found the nesting level adjustment l+(-1)^n in xnor's answer.

\$\endgroup\$
  • \$\begingroup\$ The signum seems too complicated, how about just _#0=1<0? \$\endgroup\$ – xnor Nov 16 '15 at 6:42
  • \$\begingroup\$ @xnor: yes, thanks. \$\endgroup\$ – nimi Nov 16 '15 at 6:52
  • \$\begingroup\$ Why not l>0 instead of l==1? \$\endgroup\$ – Michael Klein Feb 8 '16 at 23:03
  • \$\begingroup\$ @MichaelKlein: because only l==1 is balanced. If l>1, the parentheses are unbalanaced. \$\endgroup\$ – nimi Feb 8 '16 at 23:15
  • \$\begingroup\$ @nimi I see, I misinterpreted how it works \$\endgroup\$ – Michael Klein Feb 8 '16 at 23:33
3
\$\begingroup\$

Python 2, 60 57 56 55 53 52 50 49 bytes

n=input()
i=1
while i*n:i+=1|n%-2;n/=2
print i==1

Thanks to xnor for saving two bytes and feersum for bringing the final byte count to 49!

Explanation

The input number, n, is processed from its least significant bit. i is a counter that keeps track of the number of 0's and 1's. Note that it is initialised to 1 to save a byte. The loop will abort before n reaches 0 if the number of 1's exceed the number of 0's (i<=0).

For the parentheses to be balanced, two conditions are required:

  • The number of 0's and 1's are equal (i.e. i==1)
  • The number of 1's never exceeds the number of 0's during this process (i.e the loop doesn't abort prematurely so n==0). Edit: I realised that this condition isn't necessary as i must be non-positive if n!=0 so the previous condition is sufficient.
\$\endgroup\$
  • \$\begingroup\$ If i and n are nonnegative then i==n==0 is i+n==0. \$\endgroup\$ – orlp Nov 16 '15 at 4:26
  • \$\begingroup\$ i can be negative if the loop aborts prematurely. \$\endgroup\$ – xsot Nov 16 '15 at 4:27
  • \$\begingroup\$ Actually, i|n==0 should always work. \$\endgroup\$ – orlp Nov 16 '15 at 4:30
  • \$\begingroup\$ Great suggestion, that line looks better now. \$\endgroup\$ – xsot Nov 16 '15 at 4:32
  • \$\begingroup\$ while i*n should work \$\endgroup\$ – xnor Nov 16 '15 at 8:32
3
\$\begingroup\$

JavaScript ES5, 118 87 85 82 77 bytes

Interesting technique in my opinion. Minus a whole heck of a lot, thanks to @ETHproductions, and @NotthatCharles

function p(x){x=x.toString(2);while(/10/.test(x))x=x.replace(10,"");return!x}

JavaScript ES6, 77 57 56 54 bytes

-21 bytes to ETHproductions.

x=>[...x=x.toString(2)].map(_=>x=x.replace(10,""))&&!x
\$\endgroup\$
  • \$\begingroup\$ I like the translation to parentheses. However, if you leave it as 1s and 0s, it's a good bit shorter: function p(x){x=x.toString(2);r=/10/;while(x.search(r)>=0){x=x.replace(r,"")}return!x} \$\endgroup\$ – ETHproductions Nov 16 '15 at 18:36
  • \$\begingroup\$ @ETHproductions Good point! I think I'll leave the other code at the bottom, I really like the algorithm ^_^ Thanks mate! \$\endgroup\$ – Conor O'Brien Nov 16 '15 at 18:37
  • \$\begingroup\$ The ES6 version can still be golfed a bunch: x=>([...x=x.toString(2)].map(_=>x=x.replace(/10/,"")),!x) The trick is to move the while loop into a .map, since there are never more '10's in an input than its length. \$\endgroup\$ – ETHproductions Nov 16 '15 at 18:57
  • \$\begingroup\$ @ETHproductions Thanks again ^_^ Nice trick with map. \$\endgroup\$ – Conor O'Brien Nov 16 '15 at 18:59
  • \$\begingroup\$ No problem :) BTW, another byte can be saved with a trick edc65 uses all the time: x=>[...x=x.toString(2)].map(_=>x=x.replace(/10/,""))&&!x IDK if it can get shorter though. \$\endgroup\$ – ETHproductions Nov 16 '15 at 19:00
2
\$\begingroup\$

D, 209 170 bytes

import std.stdio;import std.format;import std.conv;void main(char[][]a){string b=format("%b",to!int(a[1]));int i;foreach(c;b){i+=c=='1'?1:-1;if(i<0)break;}writeln(i==0);}

This does exactly what it is supposed to do without any additions or benefits.

\$\endgroup\$
2
\$\begingroup\$

C, 67 bytes

n;main(i){for(scanf("%d",&n);n*i;n/=2)i+=1-n%2*2;putchar(48+!~-i);}

Pretty much a port of my python submission.

\$\endgroup\$
2
\$\begingroup\$

Prolog, 147 bytes

b(N,[X|L]):-N>1,X is N mod 2,Y is N//2,b(Y,L).
b(N,[N]).
q([H|T],N):-N>=0,(H=0->X is N+1;X is N-1),q(T,X).
q([],N):-N=0.
p(X):-b(X,L),!,q(L,0).

How it works

b(N,[X|L]):-N>1,X is N mod 2,Y is N//2,b(Y,L).
b(N,[N]).

Converts decimal number N to it's binary representation as a list (reversed). Meaning:

b(42,[0,1,0,1,0,1]) is true

Then:

q([H|T],N):-N>=0,(H=0->X is N+1;X is N-1),q(T,X).
q([],N):-N=0.

Recurses over list [H|T] increasing N if head element is 0 otherwise decreasing it.
If N at any point becomes negative or if N in the end is not 0 return false, else true.

The cut in

p(X):-b(X,L),!,q(L,0).

Is there to prevent backtracking and finding non-binary solutions to b(N,[N])

Testing
Try it out online here
Run it with a query like:

p(42).
\$\endgroup\$
2
\$\begingroup\$

PowerShell, 106 Bytes

param($a)$b=[convert]::ToString($a,2);1..$b.Length|%{if($b[$_-1]%2){$c++}else{$c--}if($c-lt0){0;exit}};!$c

Not going to win any shortest-length competitions, that's for sure. But hey, at least it's beating Java?

Uses the very long .NET call [convert]::ToString($a,2) to convert our input number to a string representing the binary digits. We then for-loop through that string with 1..$b.length|%{..}. Each loop, if our digit is a 1 (evaluated with %2 rather than -eq1 to save a couple bytes), we increment our counter; else, we decrement it. If we ever reach negative, that means there were more ) than ( encountered so far, so we output 0 and exit. Once we're through the loop, $c is either 0 or some number >0, so we take the logical-not ! of it, which gets output.

This has the quirk of outputting 0 if the parens are mismatched because we have more ), but outputting False if the parens are mismatched because we have more (. Essentially functionally equivalent falsy statements, just interesting. If the parens all match, outputs True.

\$\endgroup\$
  • \$\begingroup\$ Okay, sure. (Well, if I can fix the nagging doubt that I'm solving the wrong problem, I will). \$\endgroup\$ – TessellatingHeckler Dec 22 '15 at 17:57
1
\$\begingroup\$

GNU Sed (with eval extension), 27

s/.*/dc -e2o&p/e
:
s/10//
t

Sed doesn't really have a defined idea of truthy and falsey, so here I am claiming that the empty string means truthy and all other strings mean falsey.

If this is not acceptable, then we can do the following:

GNU Sed (with eval extension), 44

s/.*/dc -e2o&p/e
:
s/10//
t
s/.\+/0/
s/^$/1/

This outputs 1 for truthy and 0 otherwise.

\$\endgroup\$
1
\$\begingroup\$

𝔼𝕊𝕄𝕚𝕟 (ESMin), 21 chars / 43 bytes

ô⟦ïßḂ]Ĉ⇀+$?⧺Ḁ:Ḁ‡)⅋!Ḁ)

Try it here (Firefox only).

Note that this uses variables predefined to numbers (specifically 2 and 0). There are predefined number variables from 0 to 256.

19 chars / 40 bytes, non-competitive

⟦ïßḂ]Ĉ⇀+$?⧺Ḁ:Ḁ‡)⅋!Ḁ

Try it here (Firefox only).

Decided to implement implicit output... However, previous output forms are still supported, so you get several output options!

\$\endgroup\$
  • \$\begingroup\$ because everyone measures by char count \$\endgroup\$ – phase Nov 17 '15 at 3:33
1
\$\begingroup\$

Java, 129 131 bytes

boolean T(int i){int j=0,k=0;for(char[]a=Integer.toString(i,2).toCharArray();j<a.length&&k>=0;j++){k+=a[j]=='1'?1:-1;}return k==0;}

Probably can be shortened. Explanation to come. Thanks to Geobits for 4 bytes off!

\$\endgroup\$
  • \$\begingroup\$ Is it possible to combine int k=0; with int j=0;? \$\endgroup\$ – ETHproductions Nov 16 '15 at 19:02
  • \$\begingroup\$ No, j is an inner variable in the for loop and cannot be referenced outside it. \$\endgroup\$ – GamrCorps Nov 16 '15 at 19:14
  • \$\begingroup\$ You should be able to combine the other way, though: int k=0,j=0;for(... Then you could put the char[] declaration inside the loop initializer to save a semicolon, too. \$\endgroup\$ – Geobits Nov 16 '15 at 19:38
  • \$\begingroup\$ The bigger problem is that this gives false positives. It returns true for 9, 35, 37, 38, for example. \$\endgroup\$ – Geobits Nov 16 '15 at 19:41
  • \$\begingroup\$ @Geobits oops, I didnt even realize that, will fix when I get a chance. \$\endgroup\$ – GamrCorps Nov 17 '15 at 4:44
1
\$\begingroup\$

C++, 61 bytes

I think the current C++ answer is wrong: it returns a truthy value for all even numbers, e.g. 4. Disclaimer: I was not able to use the mentioned compiler, so I used g++ 4.8.4. The problem lies in the use of the binary AND operator instead of the logical AND which is used to break early when the number of closing parentheses exceed the number of opening parentheses. This approach could work if true is represented as a word with an all true bit pattern. On my system, and probably most other systems, true is equivalent to 1; only one bit is true. Also, n/=2 is shorter than n>>=1. Here is an improved version as a function:

int f(int n,int c=0){for(;c>=0&&n;n/=2)c+=n&1?-1:1;return c;}
\$\endgroup\$
0
\$\begingroup\$

𝔼𝕊𝕄𝕚𝕟 (very noncompetitve), 6 chars / 8 bytes

!ïⓑĦⅩ

Try it here (Firefox only).

I've decided to revisit this challenge after a very, very long time. 𝔼𝕊𝕄𝕚𝕟 has gotten so much better.

The reason this is a separate answer is because the 2 versions are almost completely different.

Explanation

Converts input to binary, recursively replaces instances of 10, then checks if result is an empty string.

\$\endgroup\$
0
\$\begingroup\$

C# 98 bytes

bool f(int m){int i=0;foreach(char s in Convert.ToString((m),2)){if(s=='1')i+=2;i--;}return i==0;}

open for any suggestions. i like this challange even tho it is old-ish

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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