RosettaCodeData/Task/Parsing-RPN-calculator-algo.../Clojure/parsing-rpn-calculator-algo...

30 lines
1.3 KiB
Clojure

(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)))