4

I am writing a small calculator (with prefix notation) and I'm curious how I'd convert prefix notation to infix notation. I currently have a function, but it's being weird, and I'm not sure how to fix it. By being weird, I mean that if given ['+', x, y] it will return (() + x + () + y) which is confusing me. Here's the code.

def pre_in(read):
    #print read
    tempOp = read[0]
    body = read[1:]
    expr = []
    for i in range(len(body)-1):
        if not isinstance(body[i], list) and body[i] != " ":
            expr.append(str(body[i]))
            expr.append(tempOp)
        else:
            expr.append(str(pre_in(body[i])))
            expr.append(tempOp)
    try:
        if not isinstance(body[-1], list):
            expr.append(str(body[-1]))
        else:
            expr.append(str(pre_in(body[-1])))
    except:
        pass
    if expr != None: return "("+' '.join(expr)+")"

What am I doing wrong?

8
  • 1
    I don't understand the problem (and your code). If I have foo = ['+', x, y], the expression [foo[1], foo[0], foo[2]] will result in [x, '+', y]. Isn't that what you want? In case of nested expressions, you'd have to do simple recursion. Maybe you should give a clearer and more complex example of your input and expected output. Commented Jun 27, 2011 at 20:12
  • 1
    you could also try using a stack, that is a common way of doing prefix<->infix, the stack would also solve nested expressions. Commented Jun 27, 2011 at 20:13
  • appears to be related to previous question by same guy: stackoverflow.com/questions/6338440/small-language-in-python Commented Jun 27, 2011 at 20:15
  • Space_C0wb0y: i was aiming for something that can handle multiple terms, like ['+', 2, 3, 4, 5] would yield 2 + 3 + 4 + 5 Commented Jun 27, 2011 at 20:22
  • @Warren actually no. this is about prefix, the other was about postfix. i'm rethinking the structure of the language Commented Jun 27, 2011 at 20:22

4 Answers 4

5

Actually your code works fine.

print pre_in ( ['+', 8, 9] )

yields

(8 + 9)

EDIT: As the others have stated, maybe you want to use a stack. Here a simple sandbox implementation with some examples (it produces many parenthesis but those don't hurt):

class Calculator:
    def __init__ (self):
        self.stack = []

    def push (self, p):
        if p in ['+', '-', '*', '/']:
            op1 = self.stack.pop ()
            op2 = self.stack.pop ()
            self.stack.append ('(%s %s %s)' % (op1, p, op2) )
        elif p == '!':
            op = self.stack.pop ()
            self.stack.append ('%s!' % (op) )
        elif p in ['sin', 'cos', 'tan']:
            op = self.stack.pop ()
            self.stack.append ('%s(%s)' % (p, op) )
        else:
            self.stack.append (p)

    def convert (self, l):
        l.reverse ()
        for e in l:
            self.push (e)
        return self.stack.pop ()

c = Calculator ()

print c.convert ( ['+', 8, 9] )
print c.convert ( ['!', 42] )
print c.convert ( ['sin', 'pi'] )
print c.convert ( ['+', 'sin', '/', 'x', 2, 'cos', '/', 'x', 3] )
Sign up to request clarification or add additional context in comments.

7 Comments

i normally run it on expressions with variables, like: ['+', x, y]
Also x = 8; y = 9; print pre_in ( ['+', x, y] ) runs fine.
what i meant was ['+', 'x', 'y']
i'm sorry, i was feeding it bad input.
Aren't / x + y z and / + y z x equivalent?
|
1

If your aim is not to develop the algorithm on your own, go to this page. There are links to two pages which explain the infix->postfix and postfix->infix algorithm. (And also, if you want to know how the algorithms are implemented in javascript, you can take a look at the source code of the page.)

Comments

1

Here's a fairly simple recursive solution.

def prefix_to_infix(expr):
    if type(expr) != type([]):
        # The expression is a number or variable.
        return str(expr)
    elif len(expr) == 2:
        # This is an operator expression with 1 argument.
        return str(expr[1])
    else:
        # This is an operator expression with 2 or more arguments.
        operator = expr[0]
        left_arg = prefix_to_infix([operator] + expr[1:-1])
        right_arg = prefix_to_infix(expr[-1])
        return "({0}{1}{2})".format(left_arg, operator, right_arg)

# prefix_to_infix(['+',1,2,3,4,5]) = '((((1+2)+3)+4)+5)'
# prefix_to_infix(['+',1,2,['*',3,4,5],6,7,8]) = '(((((1+2)+(3*4*5))+6)+7)+8)'

2 Comments

But with trig functions and such?
I was working under the assumption that the syntax for your prefix expressions were of the form ['operator', arg1, arg2, ... ,argN]. I also assumed that all operators were binary operators and left associative. It wouldn't really make sense to make trig functions in infix notation but maybe I'm just misunderstanding your question.
1

At the risk of being a bit overkill for this kind of simple parsing/conversion jobs, you may want to look at pyparsing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.