pythonstackpolish-notation

Python program to convert infix to prefix notation


I keep on getting an IndexError: list index out of range, return self.data[-1] # the last element in the list; I think I know what is causing this but I have no clue how to fix it

Here is the Stack Class I used:

class Stack: 
    # LIFO Stack implementation using a Python list as underlying storage.
    def __init__(self): 
        self.data =[]   

    def __len__(self):  
        return len(self.data)

    def is_empty(self): 
        return len(self.data)==0

    def push(self, e):  
        self.data.append(e) 

    def top(self):       
        return self.data[-1] 

    def pop(self):      
        return self.data.pop()

And the corresponding code I made:

def operatorpriority(x):
    if x == "+" or x == "-":
        return 1
    elif x == "*" or x == "/":
        return 2
    else:
        return 3
    return 0

def polishnotation(A):
    # Converts Infix to Prefix Notation
    stack = Stack()
    stack.push(')')
    A = A + '('
    output = ""
    for i in range(len(A)-1, -1, -1):
        print(i)
        if A[i].isnumeric() == True:
            output+=A[i]
        elif A[i] == ")":
            stack.push(A[i])
        elif A[i] == "-" or A[i] == "+" or A[i] == "*" or A[i] == "/" or A[i] == "^":
            if A[i] == "^":
                while operatorpriority(A[i]) <= operatorpriority(stack.top()):
                    output+=stack.pop()
            else:
                while operatorpriority(A[i]) < operatorpriority(stack.top()):
                    output+=stack.pop()
            stack.push(A[i])
        elif A[i] == "(":
            while stack.is_empty()== False:
                if stack.top() != "(":
                    output+=stack.pop()
                stack.pop()
    while stack.is_empty()== False:
        output+=stack.pop()
    print(output)

        

InfixInput = input("Input infix notation: ")

polishnotation(InfixInput)

Sample Input:

(a+b)*(c-d)

Expected Output:

*+ab-cd


Solution

    1. You have A = A + '('. That adds at the wrong end. Just do A = '('+A+')' and skip the extra push.
    2. You are giving ')' the same priority as '^'. In operatorpriority, your else: should be elif x =='^':.
    3. In your elif A[i] == "(" clause, you are popping until '('. That's the wrong type of parens. And you don't break out of that loop until the stack is empty. You need to break when you get to a ')'.
    4. Your example shows (a+b)*(c+d), but your code only allows digits. I haven't changed that.

    This works:

    class Stack: 
        # LIFO Stack implementation using a Python list as underlying storage.
        def __init__(self): 
            self.data =[]   
    
        def __len__(self):  
            return len(self.data)
    
        def is_empty(self): 
            return len(self.data)==0
    
        def push(self, e):  
            self.data.append(e) 
    
        def top(self):       
            return self.data[-1] 
    
        def pop(self):      
            return self.data.pop()
    
    def operatorpriority(x):
        if x in "+-":
            return 1
        elif x in "*/":
            return 2
        elif x in "^":
            return 3
        return 0
    
    def polishnotation(A):
        # Converts Infix to Prefix Notation
        stack = Stack()
        A = '(' + A + ')'
        output = ""
        for c in A[::-1]:
            print(c)
            if c.isnumeric():
                output+=c
            elif c == ")":
                stack.push(c)
            elif c in "+-*/^":
                if c == "^":
                    while operatorpriority(c) <= operatorpriority(stack.top()):
                        output+=stack.pop()
                else:
                    while operatorpriority(c) < operatorpriority(stack.top()):
                        output+=stack.pop()
                stack.push(c)
            elif c == "(":
                while not stack.is_empty():
                    c1 = stack.pop()
                    if c1 == ')':
                        break
                    output+=c1
        while not stack.is_empty():
            output+=stack.pop()
        return output
    
    print(polishnotation('(3+4)*(5+6)'))