Programming

(Clojure) 후위 표기 계산기

steloflute 2021. 12. 16. 23:42

mutation 사용 (atom):

; (C) 2021 KIM Taegyoon
; Postfix Calculator
(require 'clojure.string)
(println "minicalc (C) 2021 KIM Taegyoon")
(println "+ - * / expt sqrt")

(defn check-num-op [stack n]
    (cond
        (< (count stack) n)
            (do (printf "Not enough operands. Required: %s. Given: %s.\n" n (count stack))
                false)
        :else true))

(defn expt [a b] (Math/pow a b))

(defn calc [a]
    (try
        (let [stack (atom [])]
                (doseq [tok (map read-string (clojure.string/split a #"\s+"))]
                    (cond
                        ('#{+ - * / expt} tok)
                            (when (check-num-op @stack 2)
                                (reset! stack (cons ((eval tok) (second @stack) (first @stack)) (nthrest @stack 2))))
                        ('#{sqrt} tok)
                            (when (check-num-op @stack 1)
                                (reset! stack (cons (Math/sqrt (first @stack)) (nthrest @stack 1))))                    
                        :else
                            (reset! stack (cons tok @stack))))
                (first @stack))
        (catch Exception e e)))

(loop []
    (print "> ") (flush)
    (let [line (read-line)]
        (when line            
            (println (calc line))
            (recur))))

 

fold 방식 (Clojure에서는 reduce) 사용:

iteration은 fold로 구현할 수 있다.

; (C) 2021 KIM Taegyoon
; Postfix Calculator
(require 'clojure.string)
(println "minicalc (C) 2021 KIM Taegyoon")
(println "+ - * / expt sqrt")

(defn check-num-op [stack n]
    (if (< (count stack) n)
        (do (printf "Not enough operands. Required: %s. Given: %s.\n" n (count stack))
            false)
        true))

(defn expt [a b] (Math/pow a b))

(defn calc1 [stack tok]
    (cond ('#{+ - * / expt} tok)
            (when (check-num-op stack 2)
                (cons ((eval tok) (second stack) (first stack)) (nthrest stack 2)))
        ('#{sqrt} tok)
            (when (check-num-op stack 1)
                (cons (Math/sqrt (first stack)) (nthrest stack 1)))
        :else
            (cons tok stack)))

(defn calc [a]
    (try
        (if (> (count (clojure.string/trim a)) 0)
            (first (reduce calc1 [] (map read-string (clojure.string/split a #"\s+"))))
            0)
    (catch Exception e e)))

(loop []
    (print "> ") (flush)
    (let [line (read-line)]
        (when line            
            (println (calc line))
            (recur))))

loop / recur 사용:

; (C) 2021 KIM Taegyoon
; Postfix Calculator
(require 'clojure.string)
(println "minicalc (C) 2021 KIM Taegyoon")
(println "+ - * / expt")

(defn expt [a b] (Math/pow a b))

(defn calc [a]
    (try
        (cond (> (count (clojure.string/trim a)) 0)
                (loop [stack '(), expr (map read-string (clojure.string/split a #"\s+"))]
                    (cond (empty? expr)
                            (first stack)
                        :else
                            (let [tok (first expr)]
                                (cond ('#{+ - * / expt} tok)
                                            (recur (cons ((eval tok) (second stack) (first stack)) (nthrest stack 2)) (rest expr))
                                        :else
                                            (recur (cons tok stack) (rest expr))))))
            :else 0)
    (catch Exception e e)))

(loop []
    (print "> ") (flush)
    (let [line (read-line)]
        (when line            
            (println (calc line))
            (recur))))

'Programming' 카테고리의 다른 글

SQL 툴 비교  (0) 2022.02.16
Import CSV File Into MySQL Table (mysqltutorial.org)  (0) 2022.02.15
Joker 사용 후기  (0) 2021.12.15
(HTML) viewport 기본 폭은 980 픽셀이다.  (0) 2021.11.09
(SQL Developer) 다량 insert할 때  (0) 2021.11.08