# Make a calculator using Reverse Polish Notation. Use recursion.
# The Reverse Polish syntax completely removes the need for parentheses.
#
# Syntax examples:
# "3 + 2" -> ["3", "2", "+"]
# "3 * 4 + 2" -> ["3", "4", "*", "2", "+"]
# "3 * (4 + 2)" -> ["3", "4", "2", "+", "*"]
#
# Example for how to evaluate ["3", "4", "2", "+", "*"]:
# Start with "4 2 +" -> "6"
# Then "3 6 *" -> "18"
# Start with the "innermost" expression and work backwards (this is the recursion part)
#
# For help, email me@bchen.dev

# Sample solution below

# Facts:
# The last element of the list must always be an operator; otherwise there is only one element

def rpn(expression: list[str]) -> int:
    operators = "+-*/"

    def eval(expression: list[str]) -> tuple[int, int]:
        """
        Evaluate RPN and return an index value pointing to the first token in the expression.
        """
        for i in range(len(expression) - 1, -1, -1):
            token = expression[i]

            if token in operators:
                right, right_token_index = eval(expression[:i])

                # for left, we need the index of the token that comes after right
                left, left_token_index = eval(expression[:right_token_index])

                if token == "+":
                    return left + right, left_token_index
                elif token == "-":
                    return left - right, left_token_index
                elif token == "*":
                    return left * right, left_token_index
                else:
                    return int(left / right), left_token_index
            else:
                # evaluate as a literal
                literal = int(token)
                return literal, i

        return (0, 0)
    
    return eval(expression)[0]


# The following test cases should pass (please copy this into your code):
tests = [
    (["3", "2", "+"], 5),
    (["3", "4", "*"], 12),
    (["3", "4", "2", "+", "*"], 18),
    ([], 0),
    (["50", "2", "/"], 25),
    (["5", "2", "/"], 2),  # for division, cast to int using int(num)
    (["5", "4", "3", "-", "*"], 5),
    (["5", "4", "6", "2", "10", "+", "*", "-", "-"], 73),
    (["3", "2", "+", "5", "*"], 25)
]
for case in tests:
    result = rpn(case[0])
    expected = case[1]
    if result == expected:
        print(f"PASS: expected {expected}, got {result} for {case[0]}")
    else:
        print(f"FAIL: expected {expected}, got {result} for {case[0]}")
