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)
Related
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)))
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.
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?
import string
# Strength of operations:
# -> [] (brackets)
# 6 -> ~ (negative)
# 5 -> #, $, & (average, maximum, minimum)
# 4 -> %, ! (modulo, factorial)
# 3 -> ^ (power)
# 2 -> *, / (multiplication, division)
# 1 -> +, - (addition, subtraction)
def BinaryOperation(exp, idx):
""" Gets an expression and an index of an operator and returns a tuple with (first_value, operator, second_value). """
first_value = 0
second_value = 0
#Get first value
idx2 = idx -1
if idx2 == 0:
first_value = exp[idx2:idx]
else:
while (idx2 > 0) and (exp[idx2] in string.digits):
idx2 -=1
if (exp[idx2] in ("-")) or (exp[idx2] in string.digits):#-5*3
first_value = exp[idx2:idx]
else:#%5*3
first_value = exp[idx2+1:idx]
#Get second value
idx2 = idx +1
if exp[idx+1] not in string.digits: #If there is something like 1*+5, second_sign will be +.
idx2 += 1 #idx2 will begin from the char after the sign.
while (idx2 < len(exp)) and (exp[idx2] in string.digits):
idx2 += 1
second_value = exp[idx+1:idx2]
return (first_value, exp[idx], second_value)
def UnaryOperation(exp, idx):
""" Gets an expression and an index of an operator and returns a tuple with (operator, value). """
#Get value
idx2 = idx+1
if exp[idx+1] not in string.digits: #If there is something like ~-5, second_sign will be -.
idx2 += 1 #idx2 will begin from the char after the sign.
while (idx2 < len(exp)) and (exp[idx2] in string.digits):
idx2 +=1
return (exp[idx], exp[idx+1:idx2])
def Brackets(exp):
idx = 0
while idx < len(exp):
if exp[idx] == "[":
#Brackets
close_bracket = exp.find("]")
if close_bracket == -1:
raise Exception("Missing closing bracket.")
exp_brackets = exp[idx+1:close_bracket]
value = str(solve(exp_brackets))
exp = exp.replace("[" + exp_brackets + "]", value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level6(exp)
def Level6(exp):
idx = 0
while idx < len(exp):
if exp[idx] in ("~"):
#Negative
sub_exp = UnaryOperation(exp, idx)
value = ~int(sub_exp[1])
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level5(exp)
def Level5(exp):
idx = 0
while idx < len(exp):
if exp[idx] in ("#", "$", "&"):
#Average, Maximum and Minimum
sub_exp = BinaryOperation(exp, idx)
first_value = int(sub_exp[0])
second_value = int(sub_exp[2])
if sub_exp[1] == "#":
value = (first_value + second_value)/2
if sub_exp[1] == "$":
value = first_value if first_value > second_value else second_value
if sub_exp[1] == "&":
value = first_value if first_value < second_value else second_value
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level4(exp)
def Level4(exp):
idx = 0
while idx < len(exp):
if exp[idx] in ("%","!"):
#Modulo and Factorial
if exp[idx] == "%":
sub_exp = BinaryOperation(exp, idx)
value = int(sub_exp[0]) % int(sub_exp[2])
if exp[idx] == "!":
sub_exp = UnaryOperation(exp, idx)
value = reduce(lambda x,y:x*y, range(1, int(sub_exp[1])+1))
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level3(exp)
def Level3(exp):
idx = 0
while idx < len(exp):
if exp[idx] in ("^"):
#Power
sub_exp = BinaryOperation(exp, idx)
value = int(sub_exp[0]) ** int(sub_exp[2])
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level2(exp)
def Level2(exp):
idx = 0
while idx < len(exp):
if exp[idx] in ("*", "/"):
#Multiplication and Division
sub_exp = BinaryOperation(exp, idx)
if sub_exp[1] == "*":
value = int(sub_exp[0]) * int(sub_exp[2])
if sub_exp[1] == "/":
value = int(sub_exp[0]) / int(sub_exp[2])
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level1(exp)
def Level1(exp):
idx = 0
while idx < len(exp):
if (exp[idx] in ("+", "-")) and (idx != 0):
#Addition and Subtraction
sub_exp = BinaryOperation(exp, idx)
if sub_exp[1] == "+":
value = int(sub_exp[0]) + int(sub_exp[2])
if sub_exp[1] == "-":
value = int(sub_exp[0]) - int(sub_exp[2])
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return exp
def solve(exp):
exp = Brackets(exp)
return float(exp) if "." in exp else int(exp)
def remove_whitespace(exp):
""" Gets a string and removes all whitespaces and tabs """
exp = exp.replace(" ", "")
exp = exp.replace("\t", "")
return exp
while True:
exp = raw_input("")
exp = remove_whitespace(exp)
print solve(exp)
I have written this program after a lot of effort, and I was wondering about the efficiency of that solution and if it's neat.
So my question is, how plain is this program and is there any better way to rewrite it?
just for the point.
>>> eval(raw_input("input calculation: "))
input calculation: 1+1
2
>>> eval(raw_input("input calculation: "))
input calculation: (6*4^2)
26
>>> eval(raw_input("input calculation: "))
input calculation: (3/2.3)*4
5.2173913043478262
for an innocent program, you can use eval
but you really shouldn't use it ever. its only real use is confusing people, and being a fun novelty if you write programs fro yourself and decide you want a calculator.
there are many ways to write a calculator function.
try some of these other answers:
Python creating a calculator
Basic calculator program in python
python calculator program
If you want to check out some custom class-based evaluation engines in Python, these might help you:
Expression Evaluator (version 1 with source)
Math Evaluator (version 2 with source)
again = True
answer = ""
while again is True:
try:
expression = raw_input("Enter your expression: ")
found = False
oper = -1
operator1 = 0
operator2 = 0
while found==False:
if (expression.find("+")>0 and expression.find("+")<len(expression)-1):
found = True
oper = expression.find("+")
operator1 = float(expression[:oper])
operator2 = float(expression[oper+1:])
print "{} + {} = {}".format(operator1,operator2,operator1+operator2)
elif(expression.find("-")>0 and expression.find("-")<len(expression)-1):
found = True
oper = expression.find("-")
operator1 = float(expression[:oper])
operator2 = float(expression[oper+1:])
print "{} - {} = {}".format(operator1,operator2,operator1-operator2)
elif(expression.find("*")>0 and expression.find("*")<len(expression)-1):
found = True
oper = expression.find("*")
operator1 = float(expression[:oper])
operator2 = float(expression[oper+1:])
print "{} * {} = {}".format(operator1,operator2,operator1*operator2)
elif(expression.find("/")>0 and expression.find("/")<len(expression)-1):
found = True
oper = expression.find("/")
operator1 = float(expression[:oper])
operator2 = float(expression[oper+1:])
print "{} / {} = {}".format(operator1,operator2,operator1/operator2)
else:
oper = -1
found = False
print "Incorrect expression, please try again"
break
again = False
answer = raw_input("Try again?: ")
if(answer == "y" or answer=="yes" or answer =="Y" or answer == "YES"):
again = True
else:
again = False
print "Thank you for playing! See you next time."
break
except:
print "Failed, check your expression and try again"
Somehow the linebreaks are not working as they should.
This is what I get:
Expected:
O meu u2 2 post
http://www.yahoo.com
1 Gosto, 0 Nao gosto
<BLANKLINE>
O meu u2 post
http://www.altavista.com
1 Gosto, 0 Nao gosto
Got:
'O meu u2 2 post\nhttp://www.yahoo.com\n1 Gosto, 0 Nao Gosto\n\nO meu u2\nhttp://www.yahoo.com\n1 Gosto, 0 Nao Gosto'
This is the code used in the function.
The important parts should be the str and showRecentComments functions
class Comments():
def __init__(self, u=None, text='', link=None):
self.u = u
self.text = text
self.link = link
self.topo = None
self.fim = None
def __str__(self):
actual = self.topo
s = ''
if actual == None:
return None
while actual != None:
if actual.seg == None:
s += str(actual)
actual = actual.seg
else:
s += str(actual) + '\n' + '\n'
actual = actual.seg
return s
def add(self,comment):
if self.topo == None:
self.topo = comment
self.fim = comment
else:
comment.seg = self.topo
self.topo.ant = comment
self.topo = comment
def remove(self,comment):
actual = self.topo
if (self.topo == self.fim) and (self.topo == comment):
self.topo = None
self.fim = None
while actual!=None:
if actual == comment:
if self.topo==comment:
actual.seg.ant = None
self.topo = actual.seg
elif self.fim==comment:
actual.ant.seg = None
self.fim = actual.ant
else:
actual.seg.ant = actual.ant
actual.ant.seg = actual.seg
break
else:
actual = actual.seg
def countLike(self):
count = 0
actual = self.topo
while actual != None:
if len(actual.likeList) >= 1:
count += 1
actual = actual.seg
else:
actual = actual.seg
return count
def showRecentComments(self,n):
count = 1
actual = self.topo
sC = ''
if actual == None:
return None
while actual != None:
if count < n:
sC += str(actual) + '\n' + '\n'
count += 1
actual = actual.seg
elif count == n:
sC += str(actual)
count += 1
actual = actual.seg
elif count > n:
break
return sC
Regards, Nelson Gregório
It looks like you're looking at the representation of the string, which will show you the newline characters as \n. If you print or write to e.g. stdout (sys.stdout.write(s)) the string instead, the newlines will be expanded.