Advertisement
Guest User

math evaluator

a guest
May 28th, 2013
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (def sin #(Math/sin %))
  2. (def cos #(Math/cos %))
  3.  
  4. (def precedence {'+ 0, '- 0, '* 1, '/ 1, 'sin 2, 'cos 2})
  5. (defn operator? [o] (not (nil? (precedence o))))
  6.  
  7. (defn tokenize [expr]
  8.   (letfn [(str-split [s] (apply list (.split s " ")))
  9.           (to-num-sym [t]
  10.             (try
  11.               (Double/parseDouble t)
  12.               (catch NumberFormatException e
  13.                 (symbol t))))]
  14.   (map to-num-sym (filter #(not (empty? %)) (str-split expr)))))
  15.  
  16. (defn apply-op [op stack]
  17.   (let [fst (first stack)
  18.         snd (second stack)
  19.         rst (drop 2 stack)]
  20.     (condp = op
  21.       '+ (cons (+ snd fst) rst)
  22.       '- (cons (- snd fst) rst)
  23.       '* (cons (* snd fst) rst)
  24.       '/ (cons (/ snd fst) rst)
  25.       'sin (cons (Math/sin fst) (rest stack))
  26.       'cos (cons (Math/cos fst) (rest stack)))))
  27.  
  28. (defn evaluate [rpn, x]
  29.   (loop [expr rpn stack '()]
  30.     (if (empty? expr)
  31.       (first stack)
  32.       (let [elem (first expr) rst (rest expr)]
  33.         (cond
  34.           (number? elem) (recur rst (cons elem stack))
  35.           (= elem 'x) (recur rst (cons x stack))
  36.           :else (recur rst (apply-op elem stack)))))))
  37.  
  38. (defn to-fn [rpn]
  39.   (loop [expr rpn result '()]
  40.     (if (empty? expr)
  41.       (eval (concat (list 'fn '[x]) result))
  42.       (let [elem (first expr) rst (rest expr)]
  43.         (if (operator? elem)
  44.           (recur rst (list (cons elem result)))
  45.           (recur rst (concat result (list elem))))))))
  46.  
  47. (defn to-rpn [infix]
  48.   (loop [expr infix result '() stack '()]
  49.     (if (empty? expr)
  50.       (reverse (into result stack))
  51.       (let [elem (first expr) rst (rest expr)]
  52.         (cond
  53.           (or (number? elem) (= elem 'x)) (recur rst (cons elem result) stack)
  54.           (= (symbol "(") elem) (recur rst result (cons elem stack))
  55.           (= (symbol ")") elem)
  56.             (let [[ops rst-stack] (split-with #(not= % (symbol "(")) stack)]
  57.               (recur rst (into result ops) (rest rst-stack)))
  58.           :else
  59.             (let [[ops rst-stack] (split-with #(and (not= % (symbol "(")) (<= (precedence elem) (precedence %))) stack)]
  60.               (recur rst (into result ops) (cons elem rst-stack))))))))
  61.  
  62. (def fn1 (to-fn (tokenize "1 2 + x * sin")))
  63. (println (fn1 2.3))
  64.  
  65. (def fn2 (to-fn (to-rpn (tokenize "sin ( ( 1 + 2 ) * x )"))))
  66. (println (fn2 2.3))
  67.  
  68. (def rpn (to-rpn (tokenize "sin ( ( 1 + 2 ) * x )")))
  69. (println (evaluate rpn 2.3))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement