Last active
March 15, 2020 11:52
-
-
Save titogarcia/13a5837dea9b16b73a58150b08f5b218 to your computer and use it in GitHub Desktop.
Roman numerals to integer in Clojure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns roman | |
| (:require | |
| [clojure.test :refer :all])) | |
| (def roman-letter->int | |
| {\I 1 | |
| \V 5 | |
| \X 10 | |
| \L 50 | |
| \C 100 | |
| \D 500 | |
| \M 1000}) | |
| (defn roman->int [roman] | |
| (first | |
| (reduce | |
| (fn [[acc max] elem] | |
| (let [val (roman-letter->int elem)] | |
| (if (>= val max) | |
| [(+ acc val) val] | |
| [(- acc val) max]))) | |
| [0 0] | |
| (reverse roman)))) | |
| (deftest roman-tests | |
| (is (= 1 (roman->int "I"))) | |
| (is (= 2 (roman->int "II"))) | |
| (is (= 3 (roman->int "III"))) | |
| (is (= 4 (roman->int "IV"))) | |
| (is (= 5 (roman->int "V"))) | |
| (is (= 40 (roman->int "XL"))) | |
| (is (= 1998 (roman->int "MCMXCVIII"))) | |
| (is (= 2020 (roman->int "MMXX"))) | |
| (is (= 4999 (roman->int "MMMMCMXCIX")))) | |
| (roman-tests) | |
| ; Second try: loop state is more explicit and less positional. | |
| (defn roman->int [roman] | |
| (loop [[letter & rest] (reverse roman) | |
| acc 0 | |
| max 0] | |
| (if-not letter | |
| acc | |
| (let [val (roman-letter->int letter)] | |
| (if (>= val max) | |
| (recur rest (+ acc val) val) ; 'recur' is still positional | |
| (recur rest (- acc val) max)))))) | |
| ; Third try: explicit with a map as reduce state | |
| (defn roman->int [roman] | |
| (let [f (fn [{acc :acc | |
| max :max} | |
| elem] | |
| (let [val (roman-letter->int elem)] | |
| (if (>= val max) | |
| {:acc (+ acc val) | |
| :max val} | |
| {:acc (- acc val) | |
| :max max})))] | |
| (:acc | |
| (reduce f {:acc 0 :max 0} (reverse roman))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment