September 17, 2018
Just Juxt #34: Read Roman numerals (4clojure #92)
Roman numerals are easy to recognize, but not everyone knows all the rules necessary to work with them. Write a function to parse a Roman-numeral string and return the number it represents.
You can assume that the input will be well-formed, in upper-case, and follow the subtractive principle. You don't need to handle any numbers greater than MMMCMXCIX (3999), the largest number representable with ordinary letters.
(ns live.test
(:require [cljs.test :refer-macros [deftest is testing run-tests]]))
(defn roman-numeral [s]
(let [symbol-values {\I 1 \V 5
\X 10 \L 50
\C 100 \D 500
\M 1000}]
(->>
(partition-by identity s)
(map (juxt first count))
(partition-all 2 1)
(map
(fn [[[symbol cardinality] [next-symbol _]]]
(let [value (symbol-values symbol)]
(* cardinality value
(if (and next-symbol
(< value (symbol-values next-symbol)))
-1 1)))))
(apply +))))
(deftest roman-numeral-test
(is (= 14 (roman-numeral "XIV")))
(is (= 827 (roman-numeral "DCCCXXVII")))
(is (= 3999 (roman-numeral "MMMCMXCIX")))
(is (= 48 (roman-numeral "XLVIII"))))
(run-tests)