30 lines
1.3 KiB
Clojure
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)))
|