Stack calculator (postfix, Python)
python
Solution
There is a problem with
elif i is '*' or '/' or 'x' or '+':
which is treated as
elif (i is '*') or ('/') or ('x') or ('+'):
which is not what you want (it's always true). You can instead use something like:
elif i in ('*', '/', 'x', '+'):
Also:
if type(i) == int:
return push_stack(s, i)
You shouldn't be returning there. You simply want:
if type(i) == int:
push_stack(s, i)
Lastly, I think a better approach would be to always use the stack, and just return the top of the stack at the end of your function. This saves you from having to create a special case for 1-element arguments to `calculate()`. Putting this all together, something along the lines of this should work:
def calculate(inputs):
stack = []
for a in inputs:
if type(a) is int:
stack.append(a)
continue
op1, op2 = stack.pop(), stack.pop()
if a == '+':
stack.append(op2 + op1)
elif a == '-':
stack.append(op2 - op1)
elif a == '*':
stack.append(op2 * op1)
elif a == '/':
stack.append(op2 / op1)
return stack.pop()
Right now this does no error-checking (e.g. for malformed expressions), but it's easy to add.
Problem
The question I'm having problem on is calculating the postfix form expressions: for example, (1, 2, '+', 3, '*'). By calculating the expression using the following algorithm: 1. If the expression only contains an integer, return that integer. 2. Otherwise, maintain a stack. Loop through the tuple and push every element to the stack. If the element is an operator, pop the first two element out of the stack, calculate the result and push the result into the stack. To illustrate, we take the example above. Initially, the stack is empty. The test case is ``` calculate((1, 2, '*', 3, '-', 2, '*', 5, '+')) 3 ``` whereas my first code was no good (hardcoded and all >< ): ``` def calculate(inputs): if len(inputs) ==1: return inputs[0] elif len(inputs) == 5: s= [] push_stack(s, inputs[0]) push_stack(s, inputs[1]) if inputs[2] == '*': A = s.pop() * s.pop() elif inputs[2] == '+': A = s.pop() + s.pop() elif inputs[2] == '-': A= s.pop() - s.pop() elif inputs[2] == '/': A = s.pop() / s.pop() s.clear() s= [A] push_stack(s, inputs[3]) if inputs[4] == '*': A = s.pop() * s.pop() elif inputs[4] == '+': A = s.pop() + s.pop() elif inputs[4] == '-': A= s.pop() - s.pop() elif inputs[4] == '/': A = s.pop() / s.pop() return A else: s= [] push_stack(s, inputs[0]) push_stack(s, inputs[1]) if inputs[2] == '*': A = s.pop() * s.pop() elif inputs[2] == '+': A = s.pop() + s.pop() elif inputs[2] == '-': A= s.pop() - s.pop() elif inputs[2] == '/': A = s.pop() / s.pop() s.clear() s= [A] push_stack(s, inputs[3]) if inputs[4] == '*': A = s.pop() * s.pop() elif inputs[4] == '+': A = s.pop() + s.pop() elif inputs[4] == '-': A= s.pop() - s.pop() elif inputs[4] == '/': A = s.pop() / s.pop() s.clear() s= [A] push_stack(s, inputs[5]) if inputs[6] == '*': A = s.pop() * s.pop() elif inputs[6] == '+': A = s.pop() + s.pop() elif inputs[6] == '-': A= s.pop() - s.pop() elif inputs[6] == '/': A = s.pop() / s.pop() s.clear() s= [A] push_stack(s, inputs[7]) if inputs[8] == '*': A = s.pop() * s.pop() elif inputs[8] == '+': A = s.pop() + s.pop() elif inputs[8] == '-': A= s.pop() - s.pop() elif inputs[8] == '/': A = s.pop() / s.pop() return A ``` Sorry for making you read that! Then I changed the style to ``` def calculate(inputs): if len(inputs) ==1: return inputs[0] else: s =[] for i in inputs: if type(i) == int: return push_stack(s, i) elif i is '*' or '/' or 'x' or '+': A = s.pop() B =s.pop() know = operator(i, A, B) C = push_stack(s, know) return C def operator(sign, one, two): if sign == '*': A = one * two elif sign == '+': A = one + two elif sign == '-': A= one - two elif sign == '/': A = one / two return A ``` Am I getting closer to the idea and how does my code improve? ** Edit ** Using IDLE: ``` >>> calculate((1, 2, '*', 3, '-')) [1] >>> calculate((1, 2, '+', 3, '*')) [1] >>> calculate((1, 2, '*', 3, '-', 2, '*', 5, '+')) [1] ``` which is not the answer I'm looking for. It should be 1 then 9 then 3.