Reputation: 247
I'm trying to create a function that will return true if the number of opening and closing parentheses in a string are equal. If they're not, I need it to return false. Currently this is not working for all strings. For example, paren_parity('p)(()ld))()(eog((h)k(j(m()(nc)fab)i)',)
returns true as it should but paren_parity('d)p))mk)bc))j((eif(()ln)o)h((ag',)
is returning True even though the number of open and closed parentheses are not the same.
def paren_parity(z):
stack = []
pushChars, popChars = "<({[", ">)}]"
for c in z :
if c in pushChars :
stack.append(c)
elif c in popChars :
if not len(stack) :
return False
else :
stackTop = stack.pop()
balancingBracket = pushChars[popChars.index(c)]
if stackTop != balancingBracket:
return False
else :
return True
return not len(stack)
Upvotes: 0
Views: 581
Reputation: 2685
This is your problem:
else :
return True
If you encounter something that isn't a parenthesis, you always return True
. So d(
will return True
as soon as you hit the d
.
You can fix it by just removing the those lines.
Upvotes: 2
Reputation: 310069
You've got a couple choices. The first is really easy, just count the number of opening parens and closing and check for equality:
def paren_parity(z):
return z.count('(') == z.count(')')
But, this will pass strings like '))))(((('
which you might not want. Otherwise, you can keep a count of the number of opened parens as you walk over the string. If the count ever goes negative, then return False
:
def paren_parity(z):
open_count = 0
for c in z:
if c == '(':
open_count += 1
if c == ')':
open_count -= 1
if open_count < 0:
return False
return open_count == 0
Of course, this still doesn't actually work for parsing programming language text because it'll fail for things like a = 5 * ('yeah!)')
(since I have a parenthesis embedded in a string). However, I'm going to assume that isn't an issue for your current problem ;-).
Upvotes: 2
Reputation: 21239
This is easily resolved with a tail recursive function, including determining if there is a 'mismatch'.
def paren_parity(z, opening=0):
if len(z) == 0:
return opening == 0
head, *tail = z
if head == "(":
opening = opening + 1
elif head == ")":
if opening == 0:
return False
opening = opening - 1
return paren_parity(tail, opening)
opening
acts as the stack you're pushing and popping from. Since you don't care as to the value, just whether it's a push or pop, holding an integer is enough.
Upvotes: -1