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.

Original source

Related problems