I want to use the stack for checking the validity of an expression that contained nested parentheses.
I wrote bellow code but when my input is [{[]}, the code doesn't return anything but I expected to return "left parentheses are more than right ones".
also when my input is (), the response instead of being "balanced" is "mismatched" !!
what is my mistake in the written code?
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def push(self, data):
self.items.append(data)
return
def pop(self):
self.items.pop()
def match(left, right):
if left == '[' and right == ']':
return True
elif left == '{' and right == '}':
return True
elif left == '(' and right == ')':
return True
else:
return False
def validity(text):
st = Stack()
for i in text:
if i in '[{(':
st.push(i)
if i in ']})':
if st.is_empty():
print('right parentheses is more than left one')
return False
else:
compare = st.pop()
if not match(compare, i):
print('mismatched')
return False
if st.is_empty():
print('balanced')
else:
print('left parentheses are more than right ones')
for j in range(4):
example = input('plz enter text ')
validity(example)
st.pop() doesn't return anything so compare is always None.
def pop(self):
return self.items.pop()
Should fix it.
Related
I'm refreshing myself on how Stacks works and am doing this exercise below.
Write a function in python that checks if paranthesis in the string are balanced or not. Possible parantheses are "{}',"()" or "[]"
is_balanced("({a+b})") --> True
is_balanced("))((a+b}{") --> False
is_balanced("((a+b))") --> True
is_balanced("))") --> False
is_balanced("[a+b]*(x+2y)*{gg+kk}") --> True
I built it on top of a stack class I previously defined
from collections import deque
class Stack:
def __init__(self):
self.stack = deque()
def push(self, val):
self.stack.append(val)
def pop(self):
return self.stack.pop()
def peek(self):
return self.stack[-1]
def is_empty(self):
return len(self.stack) == 0
def size(self):
return len(self.stack)
def is_match(self, ch1, ch2):
match_dict = {
')':'(',
']':'[',
'}':'{',
}
return match_dict[ch1] == ch2
def is_balanced(self, string):
for char in string:
if char == '(' or char == '{' or char == '[':
self.push(char)
if char == ')' or char == '}' or char == ']':
if self.is_empty():
return False
if self.is_match(char, self.pop()):
return True
And here's the answer to the exercise
from collections import deque
def is_match(ch1, ch2):
match_dict = {
')': '(',
']': '[',
'}': '{',
}
return match_dict[ch1] == ch2
def is_balanced(s):
stack = deque()
for ch in s:
if ch == '(' or ch == '{' or ch == '[':
stack.append(ch)
if ch == ')' or ch == '}' or ch == ']':
if len(stack) == 0:
return False
if is_match(ch, stack.pop()):
return True
Other than the obvious differences, I feel like my implementation is 1:1
However, here's my result:
True
True
True
True
True
And here's the result I'm supposed to get:
True
False
True
False
True
Using the debugger, I noticed that the length of the my stack is never 0, unlike the length of the answers stack, which is definitely part of the reason I'm not getting False, but I don't know how to fix it.
What exactly am I missing here?
In your algorithm, when there is a match (e.g. [ and ]), then you return True right away. That is not correct, consider this case: "[]]".
My approach:
Scan the expression string, char by char
If there is an opening bracket, push to the stack (a simple list)
If there is a closing bracket, check for match:
If the stack is empty, meaning we have a closing bracket without a matching opening, return False right away
If not matched, return False right away
If matched then move on
When all chars exhausted, check the stack:
An empty stack means all brackets matched, return True
A non-empty stack means there are more opening than closing, return False
def is_balanced(expr: str) -> bool:
"""Return True if the expression is balanced with brackets."""
opening = "([{<"
closing = ")]}>"
pairs = dict(zip(opening, closing))
stack = []
for c in expr:
if c in opening:
stack.append(c)
elif c in closing:
try:
c_open = stack.pop()
except IndexError:
# Case: Found the closing without opening
return False
if pairs[c_open] != c:
# Case: mismatched opening and closing
return False
# A non-empty stack means there are opening without closing
return not stack
I keep on getting an IndexError: list index out of range, return self.data[-1] # the last element in the list; I think I know what is causing this but I have no clue how to fix it
Here is the Stack Class I used:
class Stack:
# LIFO Stack implementation using a Python list as underlying storage.
def __init__(self):
self.data =[]
def __len__(self):
return len(self.data)
def is_empty(self):
return len(self.data)==0
def push(self, e):
self.data.append(e)
def top(self):
return self.data[-1]
def pop(self):
return self.data.pop()
And the corresponding code I made:
def operatorpriority(x):
if x == "+" or x == "-":
return 1
elif x == "*" or x == "/":
return 2
else:
return 3
return 0
def polishnotation(A):
# Converts Infix to Prefix Notation
stack = Stack()
stack.push(')')
A = A + '('
output = ""
for i in range(len(A)-1, -1, -1):
print(i)
if A[i].isnumeric() == True:
output+=A[i]
elif A[i] == ")":
stack.push(A[i])
elif A[i] == "-" or A[i] == "+" or A[i] == "*" or A[i] == "/" or A[i] == "^":
if A[i] == "^":
while operatorpriority(A[i]) <= operatorpriority(stack.top()):
output+=stack.pop()
else:
while operatorpriority(A[i]) < operatorpriority(stack.top()):
output+=stack.pop()
stack.push(A[i])
elif A[i] == "(":
while stack.is_empty()== False:
if stack.top() != "(":
output+=stack.pop()
stack.pop()
while stack.is_empty()== False:
output+=stack.pop()
print(output)
InfixInput = input("Input infix notation: ")
polishnotation(InfixInput)
Sample Input:
(a+b)*(c-d)
Expected Output:
*+ab-cd
You have A = A + '('. That adds at the wrong end. Just do A = '('+A+')' and skip the extra push.
You are giving ')' the same priority as '^'. In operatorpriority, your else: should be elif x =='^':.
In your elif A[i] == "(" clause, you are popping until '('. That's the wrong type of parens. And you don't break out of that loop until the stack is empty. You need to break when you get to a ')'.
Your example shows (a+b)*(c+d), but your code only allows digits. I haven't changed that.
This works:
class Stack:
# LIFO Stack implementation using a Python list as underlying storage.
def __init__(self):
self.data =[]
def __len__(self):
return len(self.data)
def is_empty(self):
return len(self.data)==0
def push(self, e):
self.data.append(e)
def top(self):
return self.data[-1]
def pop(self):
return self.data.pop()
def operatorpriority(x):
if x in "+-":
return 1
elif x in "*/":
return 2
elif x in "^":
return 3
return 0
def polishnotation(A):
# Converts Infix to Prefix Notation
stack = Stack()
A = '(' + A + ')'
output = ""
for c in A[::-1]:
print(c)
if c.isnumeric():
output+=c
elif c == ")":
stack.push(c)
elif c in "+-*/^":
if c == "^":
while operatorpriority(c) <= operatorpriority(stack.top()):
output+=stack.pop()
else:
while operatorpriority(c) < operatorpriority(stack.top()):
output+=stack.pop()
stack.push(c)
elif c == "(":
while not stack.is_empty():
c1 = stack.pop()
if c1 == ')':
break
output+=c1
while not stack.is_empty():
output+=stack.pop()
return output
print(polishnotation('(3+4)*(5+6)'))
I'm writing a program to take a user input of parentheses i.e. {} [] () and checking to see if they have a pair (opening and closing). I'm running into an error when running my code where i always get the return false. I've tried different ways of checking against a pre set "list" but it doesn't seem to work. I have to use the class from above too. any help is appreciated.
some example inputs are:
>>>parenthesesMatch('{[]}')
True
>>>parenthesesMatch('({})')
True
>>>parenthesesMatch('{[)]}')
False
My code:
#George flamburis
class Stack():
def __init__(self,que=[]):
self.lst = que
def __repr__(self):
return "Stack({})".format(self.lst)
def push(self, add):
self.lst.append(add)
def pop(self):
return self.lst.pop()
def isEmpty(self):
return self.lst==[]
def first(self, loc=0): #naming of this method can't be []
return self.lst[loc]
def len(self):
return len(self.lst)
def parenthesesMatch(match):
s = Stack()
end = []
for char in match:
if char in "[ { (":
s.push(char)
else:
end.append(char)
if s.len()==len(end):
for num in range(len(end)):
if s.first(num) and end[num] not in '[]' or '{}' or'()':
return False
return True
elif s.len()!=len(end):
return False
It's much easier to simply attempt to pop a closing character off the stack when you see one, and fail if that isn't possible.
pairs = dict(tuple(pair) for pair in ["()", "[]", "{}"])
# pairs["("] == ")"
# pairs["["] == "]"
# etc
def parenthesesMatch(match):
s = Stack()
for char in match:
# Not "] } )"
if char in pairs.values() and pairs[s.pop()] != char:
return False
elif char in pairs:
s.push(char)
return s.isEmpty()
def match(par):
combs = {'{': '}', '(': ')', '[': ']'}
stack = []
for char in par:
if char in '[{(':
stack.append(char)
elif char == combs[stack[len(stack) - 1]]:
stack.pop()
else:
return False
return len(stack) == 0
Comments outline my thought.
def isParenthesesMatch(s):
# to be balanced should be divisable by 2
if len(s)%2 != 0:
return False
open_paren = ['(','[','{']
open_paren_stack = list()
match_close_paren = {')' : '(',']': '[', '}' : '{'}
for item in s:
#Don't care about open
if item in open_paren:
open_paren_stack.append(item)
#if closed we should be able to pop
elif len(open_paren_stack) == 0:
return False
#if we can pop it should match up
elif open_paren_stack.pop() != match_close_paren[item]:
return False
#in case we push a bunch of open and then end with balanced pair
return len(open_paren_stack) == 0
def parenthesesMatch(match):
counter = {'{': 0, '[': 0, '(': 0, '}': 0, ']': 0, ')': 0}
parantheses = '{}[]()'
for character in match:
if character not in parantheses:
continue
counter[character] += 1
return (counter['{'] == counter['}']) and (counter['['] == counter[']']) and (counter['('] == counter[')'])
def space_check(board, position):
return board[position] == ' '
def full_board_check(board):
for i in range(1,10):
if space_check(board, i):
return False
return True
the last line is return True
why not else: return True
if the if statement returned false, won't the last return True overwrite it??
If it was
for i in range(1,10):
if space_check(board, i):
return False
else:
return True
then after the first iteration in the for loop the function would return. This would not lead the the expected behaviour. Currently, you check every space, and not just the first one
I'm trying to make a program that checks to make sure that the text is balanced in terms of brackets (so (),[],{} and not (),[,{}). I can get it to work when it is balanced, and when it is not balanced when it is missing a closing bracket (like the previous example). What I can't get it to do is come back as unbalanced if I'm missing a bracket on the left ((),],{}). I know it's trying to pop from an empty stack but can't figure out how to counter act that. My teacher has it in her Stack class that if it's trying to pop to an empty stack, then an exception is raised automatically, and I can't change her class, which is the problem, otherwise I just would have made that as false anyways and not be in this mess. So does anyone have any ideas of how to do it before that error is raised?
Here's the code:
from ListNode import *
from Stack import Stack
ch = 0
s = 0
check = True
def parbalance():
stack = Stack()
user = input("Enter a file name: ")
file = open(user)
lines = file.readlines()
for char in lines:
for ch in char:
#print(ch)
if ch in "([{":
stack.push(ch)
if ch in ")]}":
popStack = stack.pop()
if ch == "(" and popStack != ")":
check = False
elif ch == "[" and popStack != "]":
check = False
elif ch == "{" and popStack != "}":
check = False
if stack.is_empty():
check = True
print("true")
else:
check = False
print("false")
parbalance()
In case it helps, here's her Stack class:
from ListNode import *
class Stack:
def __init__(self):
self.top = None
def push(self, item):
temp = ListNode(item)
temp.set_link(self.top)
self.top = temp
#self.top = ListNode(item, self.top)
def pop(self):
if self.top == None:
raise Exception("Trying to pop from an empty stack")
temp = self.top
self.top = temp.get_link()
return temp.get_item()
def destroy(self):
self.top = None
def is_full(self):
return False
def is_empty(self):
return self.top == None
Use try to capture an error:
try:
popStack = stack.pop()
except:
# Stack is empty, set failure and bail from the function.
check = False
return
Also, note that your tests are backwards:
if ch == "(" and popStack != ")":
ch is the closing bracket and popStack is the opening bracket, so this should be:
if ch == ")" and popStack != "(":
Without this change, your code will recognize the string "(}" as balanced.
As a side note, consider returning True or False from the function instead of setting a global variable. Using global variables to return values from functions is not a good idea.
You can put the code into a try except block. Once you catch an exception you know the stack underflows. Consequently there must be an unbalanced paranthesis.
By the way: I would not use the lengthy if else chain. Instead I would work it along the following lines:
pars = {'(':')', '[':']', '{':'}'}
....
try:
...
if ch in pars.keys():
stack.push(ch)
if ch in pars.values():
if ch != pars[stack.pop()]:
return False;
except:
return False;
return stack.is_empty()
That way you could easily add other bracket symbols if required.