Skip to content

Instantly share code, notes, and snippets.

@remvee
Created November 2, 2015 09:41
Show Gist options
  • Save remvee/e992848a054eda6f619a to your computer and use it in GitHub Desktop.
Save remvee/e992848a054eda6f619a to your computer and use it in GitHub Desktop.
(ns roman [:use clojure.test])
(def num-to-dig {1 "I", 4 "IV", 5 "V", 9 "IX"
10 "X", 40 "XL", 50 "L", 90 "XC"
100 "C", 400 "CD", 500 "D", 900 "CM"
1000 "M"})
(def dig-to-num (into {} (map (fn [[k v]] [v k]) num-to-dig)))
(defn encode
"Translate a number to a roman numeral string. Returns upper case
characters (I, V, X, L, C, D and M), ignores fractions."
{:test #(are [expected number] (= expected (encode number))
"I" 1
"MCMXLIV" 1944
"MMMI" 3001
"MMMCMXCIX" 3999)}
[number]
(when (> number 0)
(let [curr (apply max (filter #(>= number %)
(keys num-to-dig)))]
(str (num-to-dig curr)
(encode (- number curr))))))
(defn decode
"Translate a roman numeral string to a number. Expects upper case
characters (I, V, X, L, C, D and M), ignores unknown characters and
assumes subtractive notation."
{:test #(are [expected string] (= expected (decode string))
8 "VIII"
99 "XCIX"
1990 "MXM"
3999 "MMMCMXCIX")}
[string]
(loop [sum 0, string string]
(if (empty? string)
sum
(let [char (last string)
curr (* (get dig-to-num (str char) 0)
(count (take-while #(= char %)
(reverse string))))]
(recur (if (> sum curr)
(- sum curr)
(+ sum curr))
(reverse (drop-while #(= char %)
(reverse string))))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment