Is there an unmatched parenthesis in this String?

3

1

Introduction

Given a String containing an arithmetic expression, your task is to output a truthy or falsey value based on whether it contains unmatched parentheses.


Input

Your program should take in a String containing an arithmetic expression. It may take input in any way except assuming it to be present in a pre-defined variable. Reading from file, input box, modal dialog box etc. is fine. Taking input as function argument is allowed as well!


Output

Your program should output a truthy or falsey value based on whether the input String contains any unmatched parentheses. It may output in any way except except writing to a variable. Writing to file, screen, console, terminal etc. is allowed. Outputting with function return is allowed as well!


Rules

  • For the purpose of this challenge, a parentheses is defined as any one of [, {, (, ), }, ]. A parentheses is said to be unmatched if it does not have any corresponding opening/closing parentheses. For example, [1+3 does contain unmatched parentheses.

  • Ordering of parentheses does not matter in this challenge. So, ]1+3[ does not contain any unmatched parentheses. {[)(}] doesn't, as well.

  • The input String will only contain following characters : {, [, (, ), ], }, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, +, -, *, / and ^.

  • Your program should output a truthy value if the input String contains an unmatched parentheses.

  • Your program should output a falsey value if the input String does not contain an unmatched parentheses.

  • You must specify the truthy and falsey values in your post.

  • The input String will never be empty.

  • If the input String does not contain any parentheses, your program should output falsey value.

  • Standard loopholes apply.


Test Cases

Input            ->            Output

"{"                            Truthy
"{{{{}}"                       Truthy
"{[]}"                         Falsey
"[]]["                         Falsey
")()()()("                     Falsey
"1+4"                          Falsey
"{)"                           Truthy
"([)]"                         Falsey
"(()"                          Truthy
"2*{10+4^3+(10+3)"             Truthy
"-6+[18-{4*(9-6)}/3]"          Falsey
"-6+[18-{4*)9-6](/3}"          Falsey

Winning Criterion

This is , so the shortest code in bytes wins!


Note

I'll be adding a similar challenge but in which order will matter, after some time! Stay Tuned!

Arjun

Posted 2017-06-03T16:10:32.810

Reputation: 4 544

I'm 99% sure this is a dupe but I can't find the older one. – Stephen – 2017-06-03T16:14:45.730

@StephenS This one is the one that came to my mind, but I don't think it's quite a dupe...

– ETHproductions – 2017-06-03T16:21:51.847

Related – Adnan – 2017-06-03T16:40:29.630

Can I use inconsistent values, given that they are always appropriately truthy or falsey? – Erik the Outgolfer – 2017-06-03T17:17:08.560

@EriktheOutgolfer Yes, you can! – Arjun – 2017-06-03T17:21:12.163

@EriktheOutgolfer I've received a different answer to that question in the past. Maybe we should clarify on this meta post for a consensus?

– musicman523 – 2017-06-03T18:05:04.587

@StephenS I don't think that this one is a dupe but the order will matter one is almost definitely a dupe of the one ETHproductions linked to – caird coinheringaahing – 2017-06-03T18:47:17.030

3

Possible duplicate of Are the brackets fully matched?

– Stephen – 2017-06-03T19:42:14.810

5@StephenS I think the fact that this is entirely orderless makes it quite different. Neither ][ or ([)] would be valid in the other challenge but are valid here. – Martin Ender – 2017-06-03T21:01:06.793

2This question's title should really make it clearer that order is irrelevant. That's not what most people think about when talking about unmatched parentheses. – None – 2017-06-05T16:30:14.100

Is (() truthy or falsey? The rules and test cases don't make it clear whether the count of parentheses is important. All answers seem to assume that the count matters though. – Zgarb – 2017-06-07T07:06:48.800

@Arjun The rules say that a paren is unmatched if "it doesn't have a corresponding opening/closing parentheses" in the string. In ((), each paren arguably has a corresponding pair; the ) is just used as a pair of two different (s. This interpretation of the task is not refuted by any test case, since the only case that has multiple parens of the same type happens to have a matching count. – Zgarb – 2017-06-07T07:29:06.083

@Zgarb Sorry, I misinterpreted your comment. (() should return truthy as it contains an unmatched paren. Thanks for pointing that out. I will add that to the test cases. :) – Arjun – 2017-06-07T07:31:39.363

Answers

3

05AB1E, 14 10 bytes

žuS¢2ô€ËP_

Try it online!

-4 thanks to Adnan.

1 for truthy, 0 for falsey.

Its main power point is the žu builtin.

Explanation:

žuS¢2ô€ËP_
žu         Push '()<>[]{}'
  S        Split into individual chars
   ¢       Count occurrences of each char in the input. For <>, the count will always be 0
    2      Push 2
     ô     Split the array into pieces of that length, corresponding to respective matching brackets
      €    Map next command over the chunks
       Ë   Check if all elements are equal. If equal, it means that the corresponding bracket type is matched. <> will always be matched, since they will never occur in the input, so they'll both always have 0 occurrences
        P  Take the product of the boolean values. <> won't affect this, since it would always be 1
         _ Logically negate, convert 1 to 0 and non-1 (always 0 in this case) to 1

Erik the Outgolfer

Posted 2017-06-03T16:10:32.810

Reputation: 38 134

4Who doesn't have a command that pushes ()<>[]{}? – caird coinheringaahing – 2017-06-03T18:48:57.040

@cairdcoinheringaahing CJam doesn't, but you can get it with [{(<>)}]`. – Esolanging Fruit – 2017-06-04T05:57:40.033

@Challenger5 You just correctly ordered the brackets so that the (<>) won't affect the stack since it's in a code block, and then the codeblock goes into the list? Well, this challenge doesn't have <>, so you could just use [{()}]\`` or{[()]}`` or even {([])}\``. Oh wait a sec, you can actually use{()}a``. – Erik the Outgolfer – 2017-06-04T06:48:19.420

@EriktheOutgolfer Yeah, I forgot about that. – Esolanging Fruit – 2017-06-04T06:52:48.557

1@Arjun They're not handled, since they'll never be in the input. – Erik the Outgolfer – 2017-06-05T07:51:19.990

4

Python 2, 47 bytes

lambda s:map(s.count,'([{')!=map(s.count,')]}')

Try it online! Test cases from musicman523.

Checks if list of counts for each type of open paren matches that for the corresponding close parens.

The program is one byte longer

q=input().count
print map(q,'([{')!=map(q,')]}')

xnor

Posted 2017-06-03T16:10:32.810

Reputation: 115 687

2

Python 2, 61 bytes

Saved 4 bytes thanks to WheatWizard!

lambda s:any(s.count(i)^s.count(j)for i,j in['{}','[]','()'])

Try it online!

musicman523

Posted 2017-06-03T16:10:32.810

Reputation: 4 472

This can be made slightly shorter by ditching r. Try it online

– Post Rock Garf Hunter – 2017-06-03T17:54:32.790

Thanks! I changed it to match the two characters into separate variables, removing the indexing and therefore saving 4 more bytes. – musicman523 – 2017-06-03T17:58:37.043

1

Jelly, 17 bytes

ċЀ“[]{}()”s2E€ẠṆ

Try it online!

1 is truthy, 0 is falsey.

Erik the Outgolfer

Posted 2017-06-03T16:10:32.810

Reputation: 38 134

1

Python 3, 62 61 bytes

Surprisingly pythonic for codegolf.

lambda x:all(x.count(y)-x.count(z)for y,z in("[]","()","{}"))

-1 byte thanks to @musicman523

L3viathan

Posted 2017-06-03T16:10:32.810

Reputation: 3 151

You can use musicman's trick to make this shorter. TIO

– Post Rock Garf Hunter – 2017-06-03T17:58:52.243

1And now we have the same answers :) Although your post came before my edit, I did come up with it independently – musicman523 – 2017-06-03T17:59:12.860

Yeah, I'll leave it as is. – L3viathan – 2017-06-03T18:00:59.950

You could change == to - and keep all, then we have the same byte count but different answers – musicman523 – 2017-06-03T18:01:44.197

@musicman523 Alright then! – L3viathan – 2017-06-03T18:04:17.850

1

MATL, 15 bytes

!'[](){}'=sHeda

This outputs 1 if unmatched, 0 if matched.

Try it online!

Explanation

!          % Implicitly input string. Tranpose into vertical vector of chars
'[](){}'   % Push this string
=          % Compare for equalty, with broadcast
s          % Sum of each column. This gives the count of each char of '[](){}'
He         % Reshape as a two-row column (in column-major order)
d          % Difference of the two entries of each column
a          % Any: gives true (1) if some entry is nonzero, false (0) otherwise
           % Implicitly display

Luis Mendo

Posted 2017-06-03T16:10:32.810

Reputation: 87 464

1

Javascript, 71 bytes:

x=>['()','[]','{}'].some(a=>x.split(a[0]).length!=x.split(a[1]).length)

asgallant

Posted 2017-06-03T16:10:32.810

Reputation: 309

1

Ruby, 58+1 = 59 bytes

+1 byte for the -n flag.

f=->c{$_.count c}
p %w"() [] {}".any?{|s|f[s[0]]!=f[s[1]]}

Try it online!

Value Ink

Posted 2017-06-03T16:10:32.810

Reputation: 10 608

1

Javascript 57 bytes

x=>(g=z=>x.split(z).length,g`(`-g`)`|g`[`-g`]`|g`{`-g`}`)

Starting from asgallant's solution.

Matching returns 0. Non-matching returns non-zero.

Steve Bennett

Posted 2017-06-03T16:10:32.810

Reputation: 1 558

0

Python 2, 85 bytes

I can definitely golf this using subtraction instead but I'm running out of time. D:

lambda s,c=str.count:(c(s,'(')!=c(s,')'))or(c(s,'{')!=c(s,'}'))or(c(s,'[')!=c(s,']'))

Try it online!

totallyhuman

Posted 2017-06-03T16:10:32.810

Reputation: 15 378

All instances of != can be -. – CalculatorFeline – 2017-06-06T21:52:21.510

This answer has already been out-golfed by a far better answer. Hence, I'd rather not try to golf this.

– totallyhuman – 2017-06-06T21:56:59.323

0

Retina, 26 bytes

O`.
+`\(\)|\[]|{}

[^*-9^]

Try it online!

Explanation

O`.

Sort all characters so that corresponding brackets are adjacent (since neither \ nor | can appear in the input).

+`\(\)|\[]|{}

Repeatedly remove pairs of matching brackets.

[^*-9^]

Try to match any remaining brackets (the regex matches anything that isn't a ^ or in the ASCII range from * to 9 which, among the valid input characters, are only the 6 brackets). If we find any, that means that there was an unmatched one. The result will be a positive integer if the input was unbalanced, 0 otherwise.

Martin Ender

Posted 2017-06-03T16:10:32.810

Reputation: 184 808

{{{{}} is matched? Your code return 0 on that input. – user202729 – 2017-06-07T14:20:07.047

@user202729 Thanks, it should be fixed now (luckily at the same byte count). – Martin Ender – 2017-06-07T15:23:46.253

0

PowerShell, 95 86 bytes

param($s)$h=@{};[char[]]$s|%{$h["$_"]++};$h.'['-$h.']'-or$h.'('-$h.')'-or$h.'{'-$h.'}'

Try it online!

Previous version

param($s)switch([char[]]$s){'('{$k++}')'{$k--}'['{$l++}']'{$l--}'{'{$m++}'}'{$m--}}$k-or$l-or$m

Try it online!

Andrei Odegov

Posted 2017-06-03T16:10:32.810

Reputation: 939

0

Javascript, 149 140 bytes

New solution incorporates bitwise operators (Thanks, arjun) and calculates if they are not equal, and uses or instead of and.

function f(x){return x.split("(").length!=x.split(")").length|x.split("{").length!=x.split("}").lengt|x.split("[").length!=x.split("]").length}

I don't yet have a snippet for this, so I'm not sure it works yet.

OLD SOLUTION:

function f(x){return !(x.split("(").length==x.split(")").length&&x.split("{").length==x.split("}").length&&x.split("[").length==x.split("]").length)}

Checks if there are the same amount of one bracket and another, and then returns the opposite.

function f(x){return !(x.split("(").length==x.split(")").length&&x.split("{").length==x.split("}").length&&x.split("[").length==x.split("]").length)}

/*"{"                            Truthy
"{[]}"                         Falsey
"[]]["                         Falsey
")()()()("                     Falsey
"1+4"                          Falsey
"{)"                           Truthy
"([)]"                         Falsey
"2*{10+4^3+(10+3)"             Truthy
"-6+[18-{4*(9-6)}/3]"          Falsey
"-6+[18-{4*)9-6](/3}"          Falsey*/

console.log(f("{"));
console.log(f("{[]}"));
console.log(f("[]]["));
console.log(f(")()()()("));
console.log(f("1+4"));
console.log(f("{)"));
console.log(f("([)]"));
console.log(f("2*{10+4^3+(10+3)"));
console.log(f("-6+[18-{4*(9-6)}/3]"));
console.log(f("-6+[18-{4*)9-6](/3}"));

vityavv

Posted 2017-06-03T16:10:32.810

Reputation: 734

I can save 3 bytes by making every == into a != And changing && to || but I'm on mobile – vityavv – 2017-06-05T18:55:58.080

I think, bitwise operators instead of logical ones will do fine. Like & instead of && and | instead of ||. – Arjun – 2017-06-07T06:54:26.583

You can remove the outermost paren after return !. – Arjun – 2017-06-07T06:55:43.627

Do you even need a space after return? – Zacharý – 2017-06-07T15:32:38.873

I think you need that space otherwise JavaScript will count it as rerurnx and throw an error – vityavv – 2017-06-07T19:43:04.707

0

C#, 87 bytes

using System.Linq;s=>s.Count(c=>c=='['|c=='{'|c=='(')==s.Count(c=>c==']'|c=='}'|c==')')

Pretty self explanatory, just test to see if the of left parenthesis equals the count of right parenthesis.

TheLethalCoder

Posted 2017-06-03T16:10:32.810

Reputation: 6 930

Please check on {). – CalculatorFeline – 2017-06-06T21:54:59.677

0

Visual Basic.Net, 218 192 Bytes

function t(m as string,v as string)
return Len(m)-Len(m.Replace(v,""))
end function
function b(q as String)
return not(t(q,"{")=t(q,"}")and t(q,"[")=t(q,"]")and t(q,"(")=t(q,")"))
end function

polyglotrealIknow

Posted 2017-06-03T16:10:32.810

Reputation: 21

"around 218 bytes" I count 217. Also, if (expr) then return false else return true can be return not (expr). – CalculatorFeline – 2017-06-06T21:54:25.430

"around 218 bytes" I count 192. Do you have a trailing newline? – CalculatorFeline – 2017-06-06T21:59:22.040

I dont know how to put line through 218 – polyglotrealIknow – 2017-06-06T22:00:36.807

<s>218</s> works. – CalculatorFeline – 2017-06-06T22:02:02.280

well I don't have trailing newline – polyglotrealIknow – 2017-06-06T22:09:13.480

0

PHP>7.1, 124 Bytes

$t=!!$p=preg_replace("#[\d+/*^-]#","",$argn);for(;$p;$p=substr($p,1,-1))$t*=chr(($o=ord($p[0]))%5?$o+2:$o+1)==$p[-1];echo$t;

Instead of #[\d+/*^-] you can use [^]{()}[] or [^\p{Pe}\p{Ps}]

IntlChar::charMirror IntlChar::charMirror($p[0])==$p[-1] instead of chr(($o=ord($p[0]))%5?$o+2:$o+1)==$p[-1] checks not if the char is an openining or closing punctation so we can not use it without additional check &$p[0]<$p[-1] +8 Bytes

Online Version

PHP, 151 bytes

A full Regex Solution

for($c=$t=!!$p=($r=preg_replace)("#[^]{()}[]#","",$argn);$p&&$c;)$p=$r(["#^{(.*)}$#","#^\[(.*)]$#","#^\((.*)\)$#"],[$a="$1",$a,$a],$p,1,$c);echo$t&!$p;

Try it online!

Jörg Hülsermann

Posted 2017-06-03T16:10:32.810

Reputation: 13 026

0

Clojure, 65 bytes

 #(let[f(frequencies %)](some not(map =(map f"[{(")(map f"]})"))))

So long keywords :/ Returns nil for falsy and true for truthy.

NikoNyrh

Posted 2017-06-03T16:10:32.810

Reputation: 2 361