Skip to content

Instantly share code, notes, and snippets.

@Alotor
Last active April 23, 2025 08:30
Show Gist options
  • Save Alotor/d9d2a748d5359e33c7eb29e1fb0a7946 to your computer and use it in GitHub Desktop.
Save Alotor/d9d2a748d5359e33c7eb29e1fb0a7946 to your computer and use it in GitHub Desktop.
Roman numerals in Clojure
;; 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