Arithmetic evaluation: Difference between revisions
Content added Content deleted
Line 648: | Line 648: | ||
: 1 > :c 1 |
: 1 > :c 1 |
||
21/4</pre> |
21/4</pre> |
||
=={{header|Clojure}}== |
|||
<lang Clojure>(def precedence '{* 0, / 0 |
|||
+ 1, - 1}) |
|||
(defn order-ops |
|||
"((A x B) y C) or (A x (B y C)) depending on precedence of x and y" |
|||
[[A x B y C & more]] |
|||
(let [ret (if (<= (precedence x) |
|||
(precedence y)) |
|||
(list (list A x B) y C) |
|||
(list A x (list B y C)))] |
|||
(if more |
|||
(recur (concat ret more)) |
|||
ret))) |
|||
(defn add-parens |
|||
"Tree walk to add parens. All lists are length 3 afterwards." |
|||
[s] |
|||
(clojure.walk/postwalk |
|||
#(if (seq? %) |
|||
(let [c (count %)] |
|||
(cond (even? c) (throw (Exception. "Must be an odd number of forms")) |
|||
(= c 1) (first %) |
|||
(= c 3) % |
|||
(>= c 5) (order-ops %))) |
|||
%) |
|||
s)) |
|||
(defn make-ast |
|||
"Parse a string into a list of numbers, ops, and lists" |
|||
[s] |
|||
(-> (format "'(%s)" s) |
|||
(.replaceAll , "([*+-/])" " $1 ") |
|||
load-string |
|||
add-parens)) |
|||
(def ops {'* * |
|||
'+ + |
|||
'- - |
|||
'/ /}) |
|||
(def eval-ast |
|||
(partial clojure.walk/postwalk |
|||
#(if (seq? %) |
|||
(let [[a o b] %] |
|||
((ops o) a b)) |
|||
%))) |
|||
(defn evaluate [s] |
|||
"Parse and evaluate an infix arithmetic expression" |
|||
(eval-ast (make-ast s))) |
|||
user> (evaluate "1 + 2*(3 - 2*(3 - 2)*((2 - 4)*5 - 22/(7 + 2*(3 - 1)) - 1)) + 1") |
|||
60</lang> |
|||
=={{header|D}}== |
=={{header|D}}== |