Task

Create a stack-based evaluator for an expression in   reverse Polish notation (RPN)   that also shows the changes in the stack as each individual token is processed as a table.



 Assume an input of a correct, space separated, string of tokens of an RPN expression
 Test with the RPN expression generated from the   Parsing/Shunting-yard algorithm   task: 

         3 4 2 * 1 5 - 2 3 ^ ^ / + 

 Print or display the output here


Notes

    ^    means exponentiation in the expression above.
    /    means division.


See also

   Parsing/Shunting-yard algorithm for a method of generating an RPN from an infix expression.
   Several solutions to 24 game/Solve make use of RPN evaluators (although tracing how they work is not a part of that task).
   Parsing/RPN to infix conversion.
   Arithmetic evaluation.


 
(ns rosettacode.parsing-rpn-calculator-algorithm
  (:require clojure.math.numeric-tower
            clojure.string
            clojure.pprint))
 
(def operators
  "the only allowable operators for our calculator"
  {"+" +
   "-" -
   "*" *
   "/" /
   "^" clojure.math.numeric-tower/expt})
 
(defn rpn
  "takes a string and returns a lazy-seq of all the stacks"
  [string]
  (letfn [(rpn-reducer [stack item] ; this takes a stack and one item and makes a new stack
            (if (contains? operators item)
              (let [operand-1 (peek stack) ; if we used lists instead of vectors, we could use destructuring, but stacks would look backwards
                    stack-1 (pop stack)]   ;we're assuming that all the operators are binary
                (conj (pop stack-1)
                      ((operators item) (peek stack-1) operand-1)))
              (conj stack (Long. item))))] ; if it wasn't an operator, we'll assume it's a long. Could choose bigint, or even read-line
    (reductions rpn-reducer [] (clojure.string/split string #"\s+")))) ;reductions is like reduce only shows all the intermediate steps
 
(let [stacks (rpn "3 4 2 * 1 5 - 2 3 ^ ^ / +")] ;bind it so we can output the answer separately.
  (println "stacks: ")
  (clojure.pprint/pprint stacks)
  (print "answer:" (->> stacks last first)))
 