reverse polish nation is also known as polish postfix notation or simply postfix notation https en wikipedia orgwikireversepolishnotation classic examples of simple stack implementations valid operators are each operand may be an integer or another expression output enter a postfix equation space separated 5 6 9 symbol action stack 5 push5 5 6 push6 5 6 9 push9 5 6 9 pop9 5 6 pop6 5 push69 5 54 pop54 5 pop5 push554 59 result 59 defining valid unary operator symbols operators their respective operation converts the given data to the appropriate number if it is indeed a number else returns the data as it is with a false flag this function also serves as a check of whether the input is a number or not parameters token the data that needs to be converted to the appropriate operator or number returns float or str returns a float if token is a number or a str if token is an operator evaluate postfix expression using a stack evaluate0 0 0 evaluate0 0 0 evaluate1 1 0 evaluate1 1 0 evaluate1 1 1 1 evaluate2 1 3 9 0 evaluate2 1 9 3 11 7 evaluate2 1 9 3 0 30000000000000027 evaluate4 13 5 6 6 evaluate2 3 1 0 evaluate4 5 6 26 0 evaluate 0 evaluate4 6 7 9 8 traceback most recent call last arithmeticerror input is not a valid postfix expression parameters postfix the postfix expression is tokenized into operators and operands and stored as a python list verbose display stack contents while evaluating the expression if verbose is true returns float the evaluated value checking the list to find out whether the postfix expression is valid print table header output in tabular format if x is operator if only 1 value is inside the stack and or is encountered then this is unary or case output in tabular format output in tabular format output in tabular format evaluate the 2 values popped from stack push result to stack output in tabular format if everything is executed correctly the stack will contain only one element which is the result create a loop so that the user can evaluate postfix expressions multiple times defining valid unary operator symbols operators their respective operation converts the given data to the appropriate number if it is indeed a number else returns the data as it is with a false flag this function also serves as a check of whether the input is a number or not parameters token the data that needs to be converted to the appropriate operator or number returns float or str returns a float if token is a number or a str if token is an operator evaluate postfix expression using a stack evaluate 0 0 0 evaluate 0 0 0 evaluate 1 1 0 evaluate 1 1 0 evaluate 1 1 1 1 evaluate 2 1 3 9 0 evaluate 2 1 9 3 11 7 evaluate 2 1 9 3 0 30000000000000027 evaluate 4 13 5 6 6 evaluate 2 3 1 0 evaluate 4 5 6 26 0 evaluate 0 evaluate 4 6 7 9 8 traceback most recent call last arithmeticerror input is not a valid postfix expression parameters post_fix the postfix expression is tokenized into operators and operands and stored as a python list verbose display stack contents while evaluating the expression if verbose is true returns float the evaluated value checking the list to find out whether the postfix expression is valid print table header append x to stack output in tabular format if x is operator if only 1 value is inside the stack and or is encountered then this is unary or case pop stack negate b output in tabular format pop stack output in tabular format pop stack output in tabular format evaluate the 2 values popped from stack push result to stack type ignore index output in tabular format if everything is executed correctly the stack will contain only one element which is the result create a loop so that the user can evaluate postfix expressions multiple times
UNARY_OP_SYMBOLS = ("-", "+")


OPERATORS = {
    "^": lambda p, q: p**q,
    "*": lambda p, q: p * q,
    "/": lambda p, q: p / q,
    "+": lambda p, q: p + q,
    "-": lambda p, q: p - q,
}


def parse_token(token: str | float) -> float | str:
    
    if token in OPERATORS:
        return token
    try:
        return float(token)
    except ValueError:
        msg = f"{token} is neither a number nor a valid operator"
        raise ValueError(msg)


def evaluate(post_fix: list[str], verbose: bool = False) -> float:
    
    if not post_fix:
        return 0
    
    valid_expression = [parse_token(token) for token in post_fix]
    if verbose:
        
        print("Symbol".center(8), "Action".center(12), "Stack", sep=" | ")
        print("-" * (30 + len(post_fix)))
    stack = []
    for x in valid_expression:
        if x not in OPERATORS:
            stack.append(x)  
            if verbose:
                
                print(
                    f"{x}".rjust(8),
                    f"push({x})".ljust(12),
                    stack,
                    sep=" | ",
                )
            continue
        
        
        
        if x in UNARY_OP_SYMBOLS and len(stack) < 2:
            b = stack.pop()  
            if x == "-":
                b *= -1  
            stack.append(b)
            if verbose:
                
                print(
                    "".rjust(8),
                    f"pop({b})".ljust(12),
                    stack,
                    sep=" | ",
                )
                print(
                    str(x).rjust(8),
                    f"push({x}{b})".ljust(12),
                    stack,
                    sep=" | ",
                )
            continue
        b = stack.pop()  
        if verbose:
            
            print(
                "".rjust(8),
                f"pop({b})".ljust(12),
                stack,
                sep=" | ",
            )

        a = stack.pop()  
        if verbose:
            
            print(
                "".rjust(8),
                f"pop({a})".ljust(12),
                stack,
                sep=" | ",
            )
        
        stack.append(OPERATORS[x](a, b))  
        if verbose:
            
            print(
                f"{x}".rjust(8),
                f"push({a}{x}{b})".ljust(12),
                stack,
                sep=" | ",
            )
    
    
    if len(stack) != 1:
        raise ArithmeticError("Input is not a valid postfix expression")
    return float(stack[0])


if __name__ == "__main__":
    
    while True:
        expression = input("Enter a Postfix Expression (space separated): ").split(" ")
        prompt = "Do you want to see stack contents while evaluating? [y/N]: "
        verbose = input(prompt).strip().lower() == "y"
        output = evaluate(expression, verbose)
        print("Result = ", output)
        prompt = "Do you want to enter another expression? [y/N]: "
        if input(prompt).strip().lower() != "y":
            break