I have a class Stack that looks like this.
I have this function that checks if given string of parenthesis is valid or not.
After debugging and printing current character and character at peak:
This output matches condition at line 40 ans is supposed to pop the element. But does not.
Here is the full code.
class Stack:
def __init__(self):
self.item = []
def push(self, item):
self.item.append(item)
def pop(self):
self.item.pop()
def isEmpty(self):
return self.item == []
def peek(self):
if not self.isEmpty():
return self.item[-1]
else:
return "Stack is Empty."
def getStack(self):
return self.item
s = Stack()
string = "{[{()}][]}"
print(list(string))
def isValid(String):
for char in string:
# print(char)
print("Peak -> " +s.peek())
print("char -> " + char)
if char == "(" or char == "[" or char == "{":
s.push(char)
elif (char == ")" and s.peek == "("):
s.pop()
elif (char == "]" and not s.isEmpty() and s.peek == "["):
s.pop()
elif (char == "}" and not s.isEmpty() and s.peek == "{"):
s.pop()
else:
return False
return s.isEmpty()
print(isValid(string))
Before checking if statement, char -> ) and s.peak returns -> (.
So, it should be popped but instead doesnt run any if statement and returns false.
(P.S if I use or instead of and, it works(at least for couple I've tried). Shouldn't it work for and and not for or )
Am I missing something? help, someone!
You are comparing strings with function object s.peek == "[". You need to call s.peek().
Change your elif conditions to this
elif char == ")" and s.peek() == "(":
s.pop()
elif (char == "]" and not s.isEmpty() and s.peek() == "["):
s.pop()
elif (char == "}" and not s.isEmpty() and s.peek() == "{"):
s.pop()
Related
Given a string that contains only the following => ‘{‘, ‘}’, ‘(‘, ‘)’, ‘[’, ‘]’. At some places there is ‘X’ in place of any bracket. Determine whether by replacing all ‘X’s with appropriate bracket, is it possible to make a valid bracket sequence.
Examples:
Input : S = "{(X[X])}"
Output : Balanced
Input : S = "[{X}(X)]"
Output : Not balanced
I tried to work it out like this, and it works for examples above. But it doesn't work for all examples eg. (it should be balanced but it says it's not)
Input: S = "([X}])"
Output: Not balanced
I tried to work it out but i can't find a solution. Please help.
class Stack:
def __init__(self):
self.data = []
def insert(self, x):
self.data.append(x)
def empty(self):
return len(self.data) == 0
def remove(self):
if self.empty():
raise ValueError('Stack is empty.')
self.data.pop()
def top_element(self):
if self.empty():
raise ValueError('Stack is empty.')
return self.data[-1]
def is_matching(a, b):
if a == "(" and b == ")":
return True
elif a == "[" and b == "]":
return True
elif a == "{" and b == "}":
return True
elif a == "X":
return True
return False
def is_balanced(expression,elements=Stack(),ind=0):
if ind == len(expression):
return elements.empty()
pre_brackets = "([{"
post_brackets = ")]}"
char = expression[ind]
if char in pre_brackets:
elements.insert(char)
return is_balanced(expression,elements,ind+1)
elif char in post_brackets:
if elements.empty() :
return False
if not is_matching(elements.top_element(), char):
return False
elements.remove()
return is_balanced(expression,elements,ind+1)
elif char == "X":
temp = Stack()
temp.insert(char)
result = (is_balanced(expression,temp,ind+1))
if result:
return True
if elements.empty():
return False
elements.remove()
return is_balanced(expression,elements,ind+1)
expression = "([X}])"
if expression == "":
print("No brackets in expression!")
elif len(expression) % 2 != 0:
print("Not balanced")
elif is_balanced(expression):
print("Balanced")
else:
print("Not Balanced")
You can do it by recursively testing all possible replacements for an X:
def can_be_balanced(expr):
pairs = "{}[]()"
opening_brackets = pairs[::2]
closing_brackets = pairs[1::2]
closer = {o:c for o, c in zip(opening_brackets, closing_brackets)}
opener = {c:o for o, c in zip(opening_brackets, closing_brackets)}
stack = []
for item in expr:
if item in opening_brackets:
# we append opening brackets to the stack
stack.append(item)
elif item in closing_brackets:
if not stack or stack[-1] != opener[item]:
# the closing bracket doesn't match the top of the stack
return False
else:
# if it does, we remove the matching opening bracket
stack.pop()
elif item == 'X':
# X could be any of the opening brackets,
possible = list(opening_brackets)
if stack and stack[-1] in opening_brackets:
# or the closing bracket matching the top of the stack
possible.append(closer[stack[-1]])
for pos in possible:
# we replace this X, the first one remaining in expr
test_expr = expr.replace('X', pos, 1)
if can_be_balanced(test_expr):
# This is just in order to print the working solution we just found,
# you may remove these two lines
if not 'X' in test_expr:
print(test_expr)
return True
# None of the replacements for X gave a balanced expression
return False
else:
raise ValueError(f'Invalid item {item} in {expr}')
# The expression is balanced if and only if the stack ends up empty
return not stack
Testing on your sample data:
tests = [("[{X}(X)]", False),
("{(X[X])}", True),
("([X}])", True),
]
for test in tests:
print(test[0], ': should be', test[1])
print(can_be_balanced(test[0]))
print('-'*20)
correctly outputs (with the balanced expression in case it can be done):
[{X}(X)] : should be False
False
--------------------
{(X[X])} : should be True
{([[]])}
True
--------------------
([X}]) : should be True
([{}])
True
--------------------
Note that a major problem in your code is that you only test the end of the expression, starting at the position of the X. Beware also of the mutable default argument elements=Stack() that would leave you with the remnants of the previous call to the function instead of a fresh, empty Stack object.
I need to write a function that given a string with parenthesis and/or square brackets it is able to evaluate if they appear in the correct order. For example, in this string '([b])(aa)' you can see that every time a parenthesis or square bracket is open, it is closed in the correct position. However, a string like '[(a])' it is not closing the parenthesis or square brackets in the correct order as it should be '[(a)]'.
The function should return True or False depending on this correct position of both elements. I have tried the following code, but this logic seems to be infinite and it is not working if I have more than two parenthesis or square brackets opened.
def parenthesis(string):
for a in range(len(string)):
if string[a] == "(":
for b in range(a,len(string)):
if string[b] == "[":
for c in range(b,len(string)):
if string[c] == "]":
for d in range(c,len(string)):
if string[d] == ")":
return True
elif string[b] == ")":
return True
else:
return False
If I run the function over the string "([b])(aa)" it is returning false as output.
parenthesis("([b])(aa)")
How can I rewrite this function so it evaluates all the parenthesis and square brackets combinations properly?
If a right parenthesis is open before a left, you got -1 and return False
def is_balanced(string):
cnt = 0
for char in string:
if char == '(': cnt += 1
if char == ')': cnt -= 1
if cnt < 0: return False
return True if cnt == 0 else False
This is one of the stack implementations I know:
def is_balanced(s):
stack = []
for char in s:
if char == "(" or char == "{" or char == "[":
stack.append(char)
elif len(stack) <= 0:
return False
elif char == ")" and stack.pop() != "(":
return False
elif char == "]" and stack.pop() != "[":
return False
elif char == "}" and stack.pop() != "{":
return False
if len(stack) == 0:
return True
return False
This version is more DRY than the prior answer:
def is_balanced(parens: str) -> bool:
# Link: https://stackoverflow.com/a/73341167/
parens_map ={'(':')','{':'}','[':']'}
stack = []
for paren in parens:
if paren in parens_map: # is open
stack.append(paren)
elif paren in parens_map.values(): # is close
if (not stack) or (paren != parens_map[stack.pop()]):
return False
return not stack
i've implemented the infix-to-prefix converter using stack , the power operator has right to left association , which drove me nuts trying to implement it.
here is my code :
def infix_to_postfix_converter(string):
def pop_untill_open_parentheses():
while not stack.is_empty() and stack.peek() != '(':
output.append(stack.pop())
stack.pop()
def pop_all_the_higher_precedences(operator):
while not stack.is_empty() and precedence(stack.peek()) >= precedence(operator):
if stack.peek() != '(':
output.append(stack.pop())
else:
break
stack.push(operator)
def precedence(operator):
operators = {'(': 3,
')': 3,
'^':2,
'*': 1,
'/': 1,
'+': 0,
'-': 0,
}
return operators[operator]
stack = Stack()
output = []
for literal in string:
if literal.isalpha():
output.append(literal)
elif literal == '(':
stack.push(literal)
elif literal == ')':
pop_untill_open_parentheses()
else:
pop_all_the_higher_precedences(literal)
while not stack.is_empty():
output.append(stack.pop())
return ''.join(output)
so the solution is , if there is a '^' in the stack and another '^' came to be pushed it'll be pushed on top of the first '^' without poping it .
my solution :
add this compare function:
def compare(operatora,operatorb):
if operatora==operatorb=='^':
return False
else:
return precedence(operatora)>=precedence(operatorb)
and modify the pop_all_the_higher_precedence function:
def pop_all_the_higher_precedences(operator):
while not stack.is_empty() and compare(stack.peek(),operator):
if stack.peek() != '(':
output.append(stack.pop())
else:
break
stack.push(operator)
I am trying to write a compiler and read in a file one character at a time. If I were to find "/" followed by another "/" then I want to interpret the rest of my line as a comment. I am using file.read(1) each time I want another character. However, if I see that I have "/" followed by something that is not a "/" is there any way I can move the file stream back one character so as to not lose that character?
def tokenType(self):
# PAGE 108
if (self.current == '{' or self.current == '}' or self.current == '(' or self.current == ')' or self.current == '[' or self.current == ']' or self.current == '.' or self.current == ',' or self.current == ';' or self.current == '-' or self.current == '*' or self.current == '/' or self.current == '&' or self.current == '|' or self.current == '<' or self.current == '>' or self.current == '=' or self.current == '~'):
if (self.current == '/'):
next = self.file.read(1)
if (next == '/'):
while (next != "\n"):
next = self.file.read(1)
return "IGNORE"
if (next == '*'):
while (True):
next = self.file.read(1)
if (next == '*'):
next = self.file.read(1)
if (next == '/'):
break
return "IGNORE"
else:
return "SYMBOL"
return "SYMBOL"
elif (self.current == " " or self.current == "\n"):
return "IGNORE"
elif (self.current == "'"):
while(next != "'"):
self.current = self.current + next
return "STRING_CONST"
elif (type(self.current) == int):
next = self.file.read(1)
while(next != " "):
self.current = self.current + next
return "INT_CONST"
else:
next = self.file.read(1)
while(next != " " and next != ""):
self.current = self.current + next
next = self.file.read(1)
if (self.current == 'class' or self.current == 'constructor' or self.current == 'function' or self.current == 'method' or self.current == 'field' or self.current == 'static' or self.current == 'var' or self.current == 'int' or self.current == 'char' or self.current == 'boolean' or self.current == 'void' or self.current == 'true' or self.current == 'false' or self.current == 'null' or self.current == 'this' or self.current == 'let' or self.current == 'do' or self.current == 'if' or self.current == 'else' or self.current == 'while' or self.current == 'return'):
return "KEYWORD"
else:
return "IDENTIFIER"
My problem seems to be when I have something like 10/5 and my program checks to see if the next character is a "/". Then on the next pass through my character interpreting function, the 5 has already been removed when it was checking for a comment.
So, is there any way I can get a character from a file stream without it being "removed" from the stream or is there a way I can move it back a character when I hit a case like this?
It's not pretty, but you could pass the current and next symbol into your function if you don't mind reading the entire file into memory. You would only need some way to track ignoring the next character.
data = open('input_file').read()
for first, second in zip(data, data[1:]):
tokenType(first, second)
But like roippi says, there are better ways to lex input.
This is my first time asking a question on here, and I am only doing this because I have spent the past week trying to figure this out and haven't been able to. I found similar questions, but the results did not help me. I have to take an infix expression and calculate the results using two stacks, one for the operator and one for the numbers. An example would be 6 - ( 5 - 3 ) * ( 4 + 2 ) = -6 or 3 * 11 / 8 + 5 – 4 * 7 = -18.875. I just cannot figure out how to get this to work. Currently my code is this:
class NumStack:
def __init__(self):
"""Create an empty stack."""
self._data = [] #nonpublic list instance
def __len__(self):
"""Return the number of elements in the stack."""
return len(self._data)
def is_empty(self):
"""Return True if the stack is empty."""
return len(self._data) == 0
def push(self,e):
"""Add element e to the top of the stack."""
self._data.append(e) #new item stored at end of list
print(self._data)
def top(self):
"""Return (but do not remove) the element at the top of the stack.
Raise Empty exception if the stack is empty"""
if self.is_empty():
return
return self._data[-1] #the last item in the list
def pop(self):
"""Remove and return the element from the top of the stack (i.e, LIFO)
Raise Empty exception if the stack is empty."""
if self.is_empty():
return "empty"
return self._data.pop() #remove last item from list
def str(self):
return self._data
class OperatorStack:
def __init__(self):
"""Create an empty stack."""
self._data = [] #nonpublic list instance
def __len__(self):
"""Return the number of elements in the stack."""
return len(self._data)
def is_empty(self):
"""Return True if the stack is empty."""
length = len(self._data)
if length == 0:
return True
else:
return False
def push(self,e):
"""Add element e to the top of the stack."""
self._data.append(e) #new item stored at end of list
print(self._data)
def top(self):
"""Return (but do not remove) the element at the top of the stack.
Raise Empty exception if the stack is empty"""
if self.is_empty():
return
return self._data[-1] #the last item in the list
def pop(self):
"""Remove and return the element from the top of the stack (i.e, LIFO)
Raise Empty exception if the stack is empty."""
length = len(self)
if length == 0:
print("list is empty")
else:
if self.is_empty():
return
return self._data.pop()
def str(self):
return self._data
def main():
expression = str(input("Enter an expression: "))
expression = expression.split()
print(expression)
N = NumStack()
O = OperatorStack()
new = []
NewOP = []
NewNum = [0,0]
for e in expression:
if e == '(' or e == ')' or e == '+' or e == '-' or e == '*' or e == '/':
O.push(e)
else:
N.push(e)
while O.is_empty() == False or N.is_empty() == False:
TmpOp = O.top()
if TmpOp == ')':
O.pop()
elif TmpOp == '(':
O.pop()
if TmpOp != '(' and TmpOp != ')':
new.append(N.pop())
new.append(O.pop())
print(TmpOp)
while TmpOp == ')':
if N.top() != "empty":
NewNum[1] = N.pop()
if N.top() != "empty":
NewNum[0] = N.top()
print(NewNum[0],NewNum[1])
if O.pop() == '+':
num = float(NewNum[1]) + float(NewNum[0])
new.append(num)
print(num)
O.pop()
break
elif O.pop() == '-':
num = float(NewNum[0]) - float(NewNum[1])
new.append(num)
print(num)
O.pop()
break
elif O.pop() == '*':
num = NewNum[1]*NewNum[0]
new.append(num)
print(num)
# O.pop()
break
elif O.pop() == '/':
num = NewNum[1]/NewNum[0]
new.append(num)
print(num)
# O.pop()
break
if O.top() == ')':
O.pop()
break
if O.__len__() == 0 and N.__len__() == 0:
break
continue
while TmpOp != ')' and TmpOp != '(':
new.append(N.pop())
new.append(O.pop())
print(new)
if O.__len__() == 0 and N.__len__() == 0:
break
print(new)
main()
I believe my classes to be correct, I just cannot find a way of extracting the needed information correctly. I am trying to pop the items into a list and when I get to a parenthesis I go ahead and perform the calculation. If I could just get the correct numbers into my list then I know I can get it to work. I just need to get the "new" to contain the correct numbers. With the problem: "6 - ( 5 - 3 ) * ( 4 + 2 )" I should get [6.0, '*', 2.0, '-', 6]. It is not coming out to that. I really appreciate any help that can be given.