Infix evaluation in Python - python

I am trying to convert the code here http://www.geeksforgeeks.org/expression-evaluation/ to python. However, I am running into some trouble and can't figure out.
class evaluateString:
def evalString(self,expression):
valueStack = []
opStack = []
i=0
while(i<len(expression)):
if(expression[i] == ' '):
continue
if(expression[i]>='0' and expression[i] <= '9'):
charNumber = [] #for storing number
while(i<len(expression) and expression[i]>='0' and expression[i] <= '9'):
charNumber.append(expression[i])
i+=1
valueStack.append(int(''.join(charNumber)))
elif (expression[i]=='('):
opStack.append(expression[i])
elif (expression[i]==')'):
while(opStack[-1]!='('):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
opStack.pop()
elif(expression[i]=='+'or expression[i]=='-'or expression[i]=='*'or expression[i]=='/'):
while( (len(opStack)!=0) and ( self.opPrecedence(expression[i],opStack[-1]) ) ):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
opStack.append(expression[i])
i = i + 1
while(len(opStack)!=0):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
return valueStack.pop()
def applyOperation(self,op,a,b):
if op=='+':
return a+b
elif op=='-':
return a-b
elif op=='*':
return a*b
elif op=='/':
return a/b
else:
return 0
def opPrecedence(self,op1,op2):
if (op2 == '(' or op2 == ')'):
return False
if ((op1 == '*' or op1 == '/') and (op2 == '+' or op2 == '-')):
return False
else:
return True
a = evaluateString()
print(a.evalString("(5+7)"))
I am able to get the right numbers in the valueStack. However, there seems to be problem in the last two elseif. Can someone point me in the right direction?

I have done some fixes and it works for some operations. But I haven't tested it for all cases. Also, operations are only integers, no floats (e.g. check last output below).
class evaluateString:
def evalString(self,expression):
valueStack = []
opStack = []
i=0
while(i<len(expression)):
if(expression[i] == ' '):
continue
if(expression[i]>='0' and expression[i] <= '9'):
charNumber = [] #for storing number
j = i
while(j<len(expression) and expression[j]>='0' and expression[j] <= '9'):
charNumber.append(expression[j])
j += 1
i = (j-1)
valueStack.append(int(''.join(charNumber)))
elif (expression[i]=='('):
opStack.append(expression[i])
elif (expression[i]==')'):
while(opStack[-1]!='('):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
opStack.pop()
elif(expression[i]=='+'or expression[i]=='-'or expression[i]=='*'or expression[i]=='/'):
while( (len(opStack)!=0) and ( self.opPrecedence(expression[i],opStack[-1]) ) ):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
opStack.append(expression[i])
i = i + 1
while(len(opStack)!=0):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
return valueStack.pop()
def applyOperation(self,op,a,b):
if op=='+':
return a+b
elif op=='-':
return b-a
elif op=='*':
return a*b
elif op=='/':
return b/a
else:
return 0
def opPrecedence(self,op1,op2):
if (op2 == '(' or op2 == ')'):
return False
if ((op1 == '*' or op1 == '/') and (op2 == '+' or op2 == '-')):
return False
else:
return True
a = evaluateString()
print(a.evalString("8*12")) #prints 96
print(a.evalString("(122-434)")) #prints -312
print(a.evalString("(232+12)/2")) #print 122
print(a.evalString("232/12+2")) #prints 21

In python eval() will evaluate infix expressions
print(eval("(5+7)/2"))
it will print the evaluated infix expression value as 6.

Related

making recursion faster using array

I was trying to get this recursion faster but when I use numbers 50 and 44.4 it takes too long my desired outcome for those numbers is -800555.6302016332
z = int(input())
x = float(input())
def rec(n):
global x
l = {}
if n == 0:
return -1
elif n == 1:
return x
elif n == 2:
return -(x+1)/3
else:
if n in l:
return l[n]
value = float((n/x)*rec(n-1) + ((-1)**n)*((n+1)/(n-1)) * rec(n-2) + ((n-1)/(2*x))*rec(n-3))
l[n] = value
return value
print(rec(z))
You are reinitializing your dictionary l = {} each time you recurse. Making l a global var should fix your problem:
l = {}
def rec(n):
global x
global l
if n == 0:
return -1
elif n == 1:
return x
elif n == 2:
return -(x+1)/3
else:
if n in l:
return l[n]
value = float((n/x)*rec(n-1) + ((-1)**n)*((n+1)/(n-1)) * rec(n-2) + ((n-1)/(2*x))*rec(n-3))
l[n] = value
return value
You could also use functools.lru_cache which does memoization for you:
import functools
#functools.lru_cache
def rec(n):
global x
if n == 0:
return -1
elif n == 1:
return x
elif n == 2:
return -(x+1)/3
else:
return float((n/x)*rec(n-1) + ((-1)**n)*((n+1)/(n-1)) * rec(n-2) + ((n-1)/(2*x))*rec(n-3))
I would also suggest avoiding the use of global variables:
import functools
def rec(n, x):
#functools.lru_cache
def recurse(n):
if n == 0:
return -1
elif n == 1:
return x
elif n == 2:
return -(x+1)/3
else:
return float((n/x)*recurse(n-1) + ((-1)**n)*((n+1)/(n-1)) * recurse(n-2) + ((n-1)/(2*x))*recurse(n-3))
return recurse(n)
def main():
n = int(input())
x = float(input())
print(rec(n, x))
if __name__ == "__main__":
main()

Inorder tree traversal with minimal parentheses

My question is how to print the expression tree in the infix notation with minimal parentheses in python. The problem is that my output differs from the desired output for examples below.
Input: 1 2 3 + -, output: (1-(2+3)), desired output: 1-(2+3).
Input: 1 2 3 4 5 6 + * + * +, output: 1+(2* 3+(4* (5+6))), desired output: 1+2*(3+4*(5+6)).
class Sav:
def __init__(self , value):
self.value = value
self.left = None
self.right = None
def operator(c):
if (c == '+' or c == '-' or c == '*' or c == '/'):
return True
else:
return False
def priority(g):
if (g == '+'):
return 0
elif (g == '-'):
return 1
elif (g == '*'):
return 2
elif (g == '/'):
return 3
else:
return -1
def tree(p):
stack = []
for char in range(len(p)):
if not operator(p[char]):
t = Sav(p[char])
stack.append(t)
else:
t = Sav(p[char])
t1 = stack.pop()
t2 = stack.pop()
t.right = t1
t.left = t2
stack.append(t)
t = stack.pop()
return t
def infix(t):
if t != None:
if t.left == None and t.right == None:
print(t.value, end='')
else:
if priority(t.value) > priority(t.right.value):
print('(', end='')
infix(t.left)
print(t.value, end='')
infix(t.right)
print(')', end='')
else:
infix(t.left)
print(t.value, end='')
infix(t.right)
postfix = []
postfix = input().split()
r = tree(postfix)
infix(r)

Recursive Hexadecimal Conversion Python 3

I've made a hexadecimal converter to practice recursion/recursive thinking. I, however, The recurssion doesn't appear to be happening as the functions seems to just output the result of 9 as of current.The code is as follows:
import math
curr=0
def convert(x):
L=len(x)
L-=1
sol=0
if L == 0:
return 0
else:
if x[curr]==["A","a"]:
v=10
elif x[curr]==["B","b"]:
v=11
elif x[curr]==["C","c"]:
v=12
elif x[curr]==["D","d"]:
v=13
elif x[curr]==["E","e"]:
v=14
elif x[curr]==["F","f"]:
v=15
else:
v=int(x[curr])
sol+=((v)*(16**(L-1)))
return sol + convert(x[curr+1])
def main():
print(convert('98A'))
main()
You were setting L = len(x) everytime you call the function. Here is one solution:
import math
def convert(x, L):
c = len(x) - 1
sol=0
if L > c:
return 0
else:
if (x[L]=="A" or x[L]=="a"):
v=10
elif (x[L]=="B" or x[L]=="b"):
v=11
elif (x[L]=="C" or x[L]=="c"):
v=12
elif (x[L]=="D" or x[L]=="d"):
v=13
elif (x[L]=="E" or x[L]=="e"):
v=14
elif (x[L]=="F" or x[L]=="f"):
v=15
else:
v=int(x[L])
sol+=((v)*(16**(c - L)))
print(sol)
return sol + convert(x, L + 1)
def main():
print(convert('98A', 0))
main()
You can use something like this:
class HexMap:
# mapping char to int
d = { hex(n)[2:]:n for n in range(16)}
def convert(x):
s = 0
# use reverse string and sum up - no need for recursion
for i,c in enumerate(x.lower()[::-1]):
s += HexMap.d[c]*16**i
return s
def main():
print(convert('98A'))
main()
Output:
2442
Recursive version:
# class HexMap: see above
def convert(x):
def convert(x,fak):
if not x:
return 0
else:
return HexMap.d[x[-1]]*16**fak + convert(x[:-1],fak+1)
return convert(x.lower(),0)
def main():
print(convert('98A'))
main()
Same output.

Calculate by using Reverse Polish Notation (Python)

I learn about Reverse Polish Notation (:RPN).
I want to calculate Numerical formula by using RPN.
I managed to write following Program.
At a glance, this code work properly.
But, when I submitted this code to Programming Contest Site, (
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0109
) I got Wrong Answer.
What is wrong with my code?
# coding: utf-8
# Convert String to List
def String2List(s):
L = []
flag = True
l = len(s)
for i in range(l):
if s[i].isdigit() and flag:
t = ""
j = 0
while s[i+j].isdigit():
t += s[i+j]
if i+j == l-1:
break
j += 1
L.append(t)
flag = False
elif not s[i].isdigit():
L.append(s[i])
flag = True
return L
# generate Reverse Polish Notation
def RPN_list(L):
S, L2 = [], []
table = {"*": 1, "/": 1, "+": 0, "-": 0, "(": -1, ")": -1}
for i in L:
if i.isdigit():
L2.append(i)
elif i == "(":
S.append(i)
elif i == ")":
while S[-1] != "(":
L2.append(S.pop())
S.pop()
else:
if len(S) != 0 and (table[S[-1]] >= table[i]):
L2.append(S.pop())
S.append(i)
while len(S) != 0:
L2.append(S.pop())
return L2
# calculate Reverse Polish Notation
def RPN_cul(L):
St = []
for i in L:
if i == '+':
St.append(int(St.pop()) + int(St.pop()))
elif i == '-':
St.append(-int(St.pop()) + int(St.pop()))
elif i == '*':
St.append(int(St.pop()) * int(St.pop()))
elif i == '/':
a = int(St.pop())
b = float(St.pop())
St.append(b/a)
else:
St.append(i)
return St[0]
N = int(raw_input())
for i in range(N):
s = raw_input()
L = String2List(s[:-1])
L = RPN_list(L)
print int(RPN_cul(L))
Result
$ python reverse_polish_notation.py
2
4-2*3=
-2
4*(8+4+3)=
60
when I fixed as follows, It was accepted. Thanks to help me.
Before:
def RPN_list(L):
...
if len(S) != 0 and (table[S[-1]] >= table[i]):
L2.append(S.pop())
S.append(i)
...
After:
def RPN_list(L):
...
while len(S) != 0 and (table[S[-1]] >= table[i]):
L2.append(S.pop())
S.append(i)
...
polish_str="123*+4-"
#scan from left to right once you got the operator make the operation save the result again perform the operation
#result=3
polish_list=[]
for i in polish_str:
polish_list.append(i)
print(polish_list)
####
temp=[]
operator=['*',"+","/","-"]
def operation(o,a,b):
if o=="+":
result=a+b
if o=="-":
result=a-b
if o=="*":
result=a*b
if o=="/":
result=a/b
return result
for i,v in enumerate(polish_list):
if v in operator:
print(temp)
leng=len(temp)
arg1=temp.pop()
print("arg1==>",arg1)
arg2=temp.pop()
print("arg2==>",arg2)
result=operation(v,arg1,arg2)
print("result==>",result)
temp.append(result)
print("temp in iteration==>",temp)
else:
temp.append(i)
print("***final temp***",temp)

How to handle functions call in RPN

I'm having a lot of trouble converting infix notation to postfix.
For instance, I want to convert this
test(a(b+c), d()) - 3
into this
b c + a , d test 3 -
I tried this solution,
def composition(s):
i = 0
rpnstack = []
stack = []
ret = []
count = 0
while i < len(s) :
if i + 1 < len(s) and s[i + 1] == "(":
stack.append([count, rpnstack, s[i]])
i += 2
count = 1
rpnstack = []
elif s[i] == "(":
count += 1
rpnstack.append(s[i])
i += 1
elif s[i] == ")":
count -= 1
if count == 0:
for a in rpn(rpnstack):
ret.append(a)
a = stack.pop()
count = a[0]
rpnstack = a[1]
ret.append(a[2])
else:
rpnstack.append(s[i])
i += 1
else:
rpnstack.append(s[i])
i += 1
for a in rpn(rpnstack):
ret.append(a)
return ret
where RPN is the standard algorithm for the reverse polish notation and is is the infix string splitted with this regex
(\+|\-|\*|\/|\>|\<|\(|\)|\,)
But it only works sometimes.
This is the full implementation of the rpn function
operator = -10
operand = -20
leftparentheses = -30
rightparentheses = -40
empty = -50
operands = ["+", "-", "*", "/", ">", "<", "=", ","]
def precedence(s):
if s is '(':
return 0
elif s is '+' or '-':
return 1
elif s is '*' or '/' or '%':
return 2
else:
return 99
def typeof(s):
if s is '(':
return leftparentheses
elif s is ')':
return rightparentheses
elif s in operands:
return operator
elif s is ' ':
return empty
else :
return operand
def rpn(infix):
postfix = []
temp = []
for i in infix :
type = typeof(i)
if type is leftparentheses :
temp.append(i)
elif type is rightparentheses :
next = temp.pop()
while next is not '(' or skip > 0:
postfix.append(next)
next = temp.pop()
elif type is operand:
postfix.append(i)
elif type is operator:
p = precedence(i)
while len(temp) is not 0 and p <= precedence(temp[-1]) :
postfix.append(temp.pop())
temp.append(i)
elif type is empty:
continue
while len(temp) > 0 :
postfix.append(temp.pop())
return postfix
if i try to use the code against this infix expression:
i < test.func()
i get:
[' test.func', 'i ', '<']
and against this
i < 10
i get:
['i ', ' 10', '<']
How can I fix this?

Categories