Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (def sin #(Math/sin %))
- (def cos #(Math/cos %))
- (def precedence {'+ 0, '- 0, '* 1, '/ 1, 'sin 2, 'cos 2})
- (defn operator? [o] (not (nil? (precedence o))))
- (defn tokenize [expr]
- (letfn [(str-split [s] (apply list (.split s " ")))
- (to-num-sym [t]
- (try
- (Double/parseDouble t)
- (catch NumberFormatException e
- (symbol t))))]
- (map to-num-sym (filter #(not (empty? %)) (str-split expr)))))
- (defn apply-op [op stack]
- (let [fst (first stack)
- snd (second stack)
- rst (drop 2 stack)]
- (condp = op
- '+ (cons (+ snd fst) rst)
- '- (cons (- snd fst) rst)
- '* (cons (* snd fst) rst)
- '/ (cons (/ snd fst) rst)
- 'sin (cons (Math/sin fst) (rest stack))
- 'cos (cons (Math/cos fst) (rest stack)))))
- (defn evaluate [rpn, x]
- (loop [expr rpn stack '()]
- (if (empty? expr)
- (first stack)
- (let [elem (first expr) rst (rest expr)]
- (cond
- (number? elem) (recur rst (cons elem stack))
- (= elem 'x) (recur rst (cons x stack))
- :else (recur rst (apply-op elem stack)))))))
- (defn to-fn [rpn]
- (loop [expr rpn result '()]
- (if (empty? expr)
- (eval (concat (list 'fn '[x]) result))
- (let [elem (first expr) rst (rest expr)]
- (if (operator? elem)
- (recur rst (list (cons elem result)))
- (recur rst (concat result (list elem))))))))
- (defn to-rpn [infix]
- (loop [expr infix result '() stack '()]
- (if (empty? expr)
- (reverse (into result stack))
- (let [elem (first expr) rst (rest expr)]
- (cond
- (or (number? elem) (= elem 'x)) (recur rst (cons elem result) stack)
- (= (symbol "(") elem) (recur rst result (cons elem stack))
- (= (symbol ")") elem)
- (let [[ops rst-stack] (split-with #(not= % (symbol "(")) stack)]
- (recur rst (into result ops) (rest rst-stack)))
- :else
- (let [[ops rst-stack] (split-with #(and (not= % (symbol "(")) (<= (precedence elem) (precedence %))) stack)]
- (recur rst (into result ops) (cons elem rst-stack))))))))
- (def fn1 (to-fn (tokenize "1 2 + x * sin")))
- (println (fn1 2.3))
- (def fn2 (to-fn (to-rpn (tokenize "sin ( ( 1 + 2 ) * x )"))))
- (println (fn2 2.3))
- (def rpn (to-rpn (tokenize "sin ( ( 1 + 2 ) * x )")))
- (println (evaluate rpn 2.3))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement