Evaluating infix expression with two stacks in python - python

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.

Related

Balanced expression with replacement

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.

my pop( ) function does not delete the top element of a list, but rather a random one

I have created the following pop function:
def pop(arr):
if not isempty(arr):
topelement = arr[len(arr)-1]
arr.remove(topelement)
return topelement
And it worked correctly until I used it in order to reverse order of a stack of numbers and operators:
"3 6 2 + * 14 3 4 + + /"
into
"/ + + 4 3 14 * + 2 6 3".
In first iteration of while loop shown below it pushed "/" operator to the auxiliary stack and deleted it from the top of entry, which is OK - but in the second iteration it deleted "+" sign from the middle of the entry instead of the plus sign with the highest index.
def evaluation(eq):
entryunsplit = errpostfix(eq)
entry = entryunsplit.split()
lengthofentry = len(entry)
stack = []
while len(stack) != lengthofentry:
push(stack,pop(entry))
Could someone please explain me why didn't it delete the last element and how can I avoid that error?
I am putting the whole code below in case some other element turns out to be significant.
stack1 = []
max_size = 30
def push(arr,a):
if len(arr) < max_size:
arr.append(a)
def isempty(arr):
if len(arr) == 0:
return True
else:
return False
def top(arr):
if not isempty(arr):
return arr[len(arr)-1]
def pop(arr):
if not isempty(arr):
topelement = arr[len(arr)-1]
arr.remove(topelement)
return topelement
def errpostfix(eq):
entry = eq.split()
opstack = []
exit = []
priorities = { "+": 1, "-": 1, "*": 0, "/": 0 }
for token in entry:
if token == "(":
push(opstack,token)
elif token == "*" or token == "/" or token == "+" or token == "-":
if top(opstack) == "*" or top(opstack) == "/" or top(opstack) == "+" or top(opstack) == "-":
while not isempty(opstack) and priorities[top(opstack)] >= priorities[token]:
push(exit,pop(opstack))
isempty(opstack)
push(opstack,token)
elif token == ")":
while top(opstack) != "(":
push(exit,pop(opstack))
pop(opstack)
else:
push(exit,token)
while not isempty(opstack):
push(exit, pop(opstack))
output = " ".join(exit)
return output
def isop(ch):
if ch == "+" or ch == "-" or ch == "*" or ch == "/":
return True
else:
return False
def evaluation(eq):
entryunsplit = "3 6 2 + * 14 3 4 + + /"
entry = entryunsplit.split()
lengthofentry = len(entry)
stack = []
while len(stack) != lengthofentry:
push(stack,pop(entry))
The remove() operation on a list will delete the first occurrence of an item in that list, is not "random" (check the docs). If there are several repeated elements, the first one encountered will be the one that gets deleted. To delete the last element, simply use the built-in pop() method:
def pop(arr):
if not isempty(arr):
topelement = arr[-1]
arr.pop()
return topelement

Can't print binary heap in python

I try to make a binary heap in python but I get trouble printing it. I make sure that the logic in the program is right but when I want to try printing it I get the wrong result. This is what I want for program output:
Input:
6
1 2
1 3
1 7
2
3
2
Output:
7
3
command 1 to insert number
command 2 to display the highest number
command 3 to delete the highest number
This is my program:
class BinaryHeap:
def __init__(self):
self.items = []
def size(self):
return len(self.items)
def parent(self, i):
return (i - 1)//2
def left(self, i):
return 2*i + 1
def right(self, i):
return 2*i + 2
def get(self, i):
return self.items[i]
def get_max(self):
if self.size() == 0:
return None
return self.items[0]
def extract_max(self):
if self.size() == 0:
return None
largest = self.get_max()
self.items[0] = self.items[-1]
del self.items[-1]
self.max_heapify(0)
return largest
def max_heapify(self, i):
l = self.left(i)
r = self.right(i)
if (l <= self.size() - 1 and self.get(l) > self.get(i)):
largest = l
else:
largest = i
if (r <= self.size() - 1 and self.get(r) > self.get(largest)):
largest = r
if (largest != i):
self.swap(largest, i)
self.max_heapify(largest)
def swap(self, i, j):
self.items[i], self.items[j] = self.items[j], self.items[i]
def insert(self, key):
index = self.size()
self.items.append(key)
while (index != 0):
p = self.parent(index)
if self.get(p) < self.get(index):
self.swap(p, index)
index = p
bheap = BinaryHeap()
n = int(input())
for i in range (n):
operation= input('What would you like to do? ').split()
if operation == 1:
data = int(operation[1])
bheap.insert(data)
elif operation == 2:
print('Maximum value: {}'.format(bheap.get_max()))
elif operation == 3:
print('Maximum value removed: {}'.format(bheap.extract_max()))
elif operation == 4:
break
I need your opinion to fixed it.
operation is a list (you called split), but you compare it as an int in your if statements. Also, you should compare it against "1", "2", ... not 1, 2, ...
So:
operation = input('What would you like to do? ').split()
if operation[0] == "1":
data = int(operation[1])
bheap.insert(data)
elif operation[0] == "2":
print('Maximum value: {}'.format(bheap.get_max()))
elif operation[0] == "3":
print('Maximum value removed: {}'.format(bheap.extract_max()))
elif operation[0] == "4":
break
If you just want 7 and 3 in the output, and only after the input has been completely processed, then you should remove those verbose print statement (where you output phrases), and instead collect the output -- for instance in a list:
output = []
n = int(input())
for i in range(n):
operation = input('What would you like to do? ').split()
if operation[0] == "1":
data = int(operation[1])
bheap.insert(data)
elif operation[0] == "2":
output.append(bheap.get_max())
elif operation[0] == "3":
bheap.extract_max()
elif operation[0] == "4":
break
print("\n".join(map(str, output)))

Stack Balanced Parenthesis is not working

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()

Infix to Postfix Converter Python 2.7

I am trying to create a infix to postfix converter in python for a homework assignment, I found multiple ones online that seem simple enough but none of them meet the requirements I need. I have to use the following classes:
class Token(object):
UNKNOWN = 0 # unknown
INT = 4 # integer
MINUS = 5 # minus operator
PLUS = 6 # plus operator
MUL = 7 # multiply operator
DIV = 8 # divide operator
FIRST_OP = 5 # first operator code
def getPrecedence(self):
if self is '(':
return 0
elif self is '+'or '-':
return 1
elif self is '*' or '/':
return 2
else:
return 3
def _init_(self, value):
if type(value) == int:
self._type = Token.INT
else:
self._type = self._makeType(value)
self._value = value
def isOperator(self):
return self._type >= Token.FIRST_OP
def _str_(self):
return str(self._value)
def getType(self):
return self._type
def getValue(self):
return self._value
def _makeType(self, ch):
if ch == '*': return Token.MUL
elif ch == '/': return Token.DIV
elif ch == '+': return Token.PLUS
elif ch == '-': return Token.MINUS
else: return Token.UNKNOWN;
I had to add the getPrecedence(): method, which returns an Integer that represents the precedence level of an operator. I also had to use the following class:
from token import Token
class Scanner(object):
EOE = ';' # end-of-expression
TAB = '\t' # tab
def __init__(self, sourceStr):
self._sourceStr = sourceStr
self._getFirstToken()
def hasNext(self):
return self._currentToken != None
def next(self):
if not self.hasNext():
raise Exception, "There are no more tokens"
temp = self._currentToken
self._getNextToken()
return temp
def _getFirstToken(self):
self._index = 0
self._currentChar = self._sourceStr[0]
self._getNextToken()
def _getNextToken(self):
self._skipWhiteSpace()
if self._currentChar.isdigit():
self._currentToken = Token(self._getInteger())
elif self._currentChar == Scanner.EOE:
self._currentToken = None
else:
self._currentToken = Token(self._currentChar)
self._nextChar()
def _nextChar(self):
if self._index >= len(self._sourceStr) - 1:
self._currentChar = Scanner.EOE
else:
self._index += 1
self._currentChar = self._sourceStr[self._index]
def _skipWhiteSpace(self):
while self._currentChar in (' ', Scanner.TAB):
self._nextChar()
def _getInteger(self):
num = 0
while True:
num = num * 10 + int(self._currentChar)
self._nextChar()
if not self._currentChar.isdigit():
break
return num
I have to write a program that converts a infix expression to a postfix expression. This program should use the Token and Scanner classes (which I have included above). The program should consist of a main function that preforms the inputs and outputs, and a class named IFToPFConverter. The main function receives a input string an creates a scanner with it. The scanner is then passed as a argument to the constructor of the converter object. The converter objects convert method is then run to convert the infix expression. This method returns a list of tokens that represent the postfix string. The main function then displays this string. Here is what I have so far:
from arrayStack import ArrayStack
from token import Token
from scanner import Scanner
class IFToPFConverter(object):
def convert(self):
opStack = Stack()
postFixList = []
while self._scanner.hasNext():
currentToken = self._scanner.next()
if currentToken in '0123456789'
postFixList.append(currentToken)
elif currentToken == '(':
opStack.push(currentToken)
elif currentToken == '*':
opStack.push(currentToken)
elif currentToken == '/':
opStack.push(currentToken)
elif currentToken == '+':
opStack.push(currentToken)
elif currentToken == '-':
opStack.push(currentToken)
elif currentToken == ')':
opStack.push(currentToken)
while not opStack.isEmpty():
def main():
sourceStr = raw_input("Please enter an expression:")
scanner = Scanner(sourceStr)
conversion = IFToConverter.convert(scanner)
return conversion
main()
I don't know where to go from here, I don't even know if what I am trying to do at in my IFToPFConverter class will work. I have seen much simpler infix to postfix converters.

Categories