Last active
April 23, 2025 08:30
-
-
Save Alotor/d9d2a748d5359e33c7eb29e1fb0a7946 to your computer and use it in GitHub Desktop.
Roman numerals 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
;; Map that represent the numeric value for roman numbers | |
(def roman->num | |
{\I 1 | |
\V 5 | |
\X 10 | |
\L 50 | |
\C 100 | |
\D 500 | |
\M 1000}) | |
;; First version | |
;; We use a `loop` to iterate through the list of numbers | |
;; The `loop` is really a recursive function with some sugar syntax | |
(defn translate-roman-numerals | |
[roman] | |
(loop [nums (seq roman) | |
result 0] | |
(if-let [head (first nums)] | |
(let [value (roman->num head) | |
next (second nums) | |
next-value (roman->num next 0) | |
result | |
(if (< value next-value) | |
(- result value) | |
(+ result value))] | |
(recur (rest nums) result)) | |
result))) | |
;; Second version | |
;; Now we use sequences functions. Each step is indicated | |
(defn translate-roman-numerals | |
[roman] | |
;; ejemplo: "MCMLIV" | |
(let [real-value | |
(fn [[current next]] | |
;; IX => -1 +10 || XI => +10 +1 | |
((if (> next current) - +) current)) | |
r1 (map roman->num roman) ;; (1000 100 1000 50 1 5) | |
r2 (partition 2 1 [0] r1) ;; ((1000 100) (100 1000) (1000 50) (50 1) (1 5) (5 0) | |
r3 (map real-value r2) ;; (1000 -100 1000 50 -1 5) | |
result (reduce + r3) ;; 1954 | |
] | |
result) | |
) | |
;; Third version | |
;; It's the same but we're using the `->>` operator for simplicity | |
(defn translate-roman-numerals | |
[roman] | |
(letfn [(real-value [[current next]] | |
;; IX => -1 +10 || XI => +10 +1 | |
((if (> next current) - +) current))] | |
(->> roman | |
(map roman->num) | |
(partition 2 1 [0]) | |
(map real-value) | |
(reduce +)))) | |
;; Alternative: we can use only a reduce function | |
(defn translate-roman-numerals | |
[roman] | |
(->> roman | |
(map roman-val) | |
(partition 2 1 [0]) | |
(reduce | |
(fn [result [current next]] | |
(if (>= current next) | |
(+ result current) | |
(- result current))) | |
0))) | |
(defn test! | |
[] | |
(assert (= (translate-roman-numerals "IX") 9)) | |
(assert (= (translate-roman-numerals "XI") 11)) | |
(assert (= (translate-roman-numerals "MCMLIV") 1954)) | |
(assert (= (translate-roman-numerals "MDCXLVII") 1647)) | |
(assert (= (translate-roman-numerals "CDXCIV") 494)) | |
(assert (= (translate-roman-numerals "MMXVII") 2017)) | |
(assert (= (translate-roman-numerals "MCCCXXXVII") 1337)) | |
(assert (= (translate-roman-numerals "XLII") 42))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment