Last active
December 31, 2015 19:09
-
-
Save guilespi/8032154 to your computer and use it in GitHub Desktop.
decimal to roman
This file contains 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
(def conv-table (sorted-map 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)) | |
(defn update-result | |
"Given a current sequence with a result appends | |
n times symbols s" | |
[result n s] | |
(if (> n 0) | |
(concat result (repeat n s)) | |
result)) | |
(defn convert | |
"Actual iteration over symbol conversion table." | |
[seed] | |
(-> (reduce (fn [[number result] [roman sym]] | |
[(rem number roman) | |
(update-result result (quot number roman) sym)]) | |
[seed []] | |
(reverse conv-table)) | |
second)) | |
(defn large-numeral | |
"Given a decimal number converts to wrapped roman | |
numeral, meaning * 1000. | |
i.e. 7000 => |VII|" | |
[n] | |
(concat [:|] (convert n) [:|])) | |
(defn dec->roman | |
"Given a decimal number converts to roman numerals" | |
[number] | |
{:pre [(>= number 0)]} | |
(let [prefix (when (>= number 5000) | |
(large-numeral (quot number 1000))) | |
seed (if prefix | |
(rem number 1000) | |
number) | |
result (convert seed)] | |
(clojure.string/join (map name (concat prefix result))))) | |
;;tests | |
(deftest test-update | |
(is (= [:I] (update-result [] 1 :I))) | |
(is (= [] (update-result [] 0 :I))) | |
(is (= [:I :V :V] (update-result [:I] 2 :V)))) | |
(deftest large-numeral | |
(is (= [:| :V :|] (large-numeral 5)))) | |
(deftest test-convert | |
(is (= "I" (dec->roman 1))) | |
(is (= "IV" (dec->roman 4))) | |
(is (= "V" (dec->roman 5))) | |
(is (= "XC" (dec->roman 90))) | |
(is (= "L" (dec->roman 50))) | |
(is (= "MCMLXXXVII" (dec->roman 1987))) | |
(is (= "CDLXVII" (dec->roman 467))) | |
(is (= "|V|" (dec->roman 5000))) | |
(is (= "|VII|DCCCLXXXVIII" (dec->roman 7888))) | |
(is (thrown? AssertionError (dec->roman -1)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment