// TypeScript
function evalRPN(tokens: string[]): number {
    const stack: number[] = [];

    for (const token of tokens) {
        console.log(stack);
        switch (token) {
            case '+': {
                const r = stack.pop()!;
                const l = stack.pop()!;
                stack.push(l + r);
            } break;

            case '-': {
                const r = stack.pop()!;
                const l = stack.pop()!;
                stack.push(l - r);
            } break;

            case '*': {
                const r = stack.pop()!;
                const l = stack.pop()!;
                stack.push(l * r);
            } break;

            case '/': {
                const r = stack.pop()!;
                const l = stack.pop()!;
                stack.push(Math.trunc(l / r));
            } break;

            default: {
                stack.push(Number(token));
            } break;
        }
    }

    return stack.pop()!;
};

const evalRPN1 = evalRPN;

const evalRPN2 = (tokens: string[]): number => {
    const stack: number[] = [];

    const ops: Record

-- Haskell
evalRPN :: [String] -> Int
evalRPN [] = 0
evalRPN tokens =
    eval tokens []
  where
    eval :: [String] -> [Int] -> Int
    eval [] [n]         = n
    eval [] _           = error "malformed reverse Polish notation!"
    eval (tk:tks) stack =
      case tk of
        "+" -> let (r:l:rest) = stack in eval tks ((l + r) : rest)
        "-" -> let (r:l:rest) = stack in eval tks ((l - r) : rest)
        "*" -> let (r:l:rest) = stack in eval tks ((l * r) : rest)
        "/" -> let (r:l:rest) = stack in eval tks ((l `quot` r) : rest) -- truncates toward 0
        _   -> eval tks (read tk : stack) -- read t :: Int converts "123" or "-5" into an Int.


evaluateReversePolishNotation :: [String] -> Int
evaluateReversePolishNotation =
    head . foldl step []
  where
    step :: [Int] -> String -> [Int]
    step stack token =
      case token of
        "+" -> binOp (+)  stack
        "-" -> binOp (-)  stack
        "*" -> binOp (*)  stack
        "/" -> binOp quot stack
        _   -> (read token) : stack

    binOp :: (Int -> Int -> Int) -> [Int] -> [Int]
    binOp op (r:l:rest) = (l `op` r) : rest
    binOp _ _           = error "malformed reverse Polish notation!"