I saw this post on Roman Numerals in Clojure: http://www.jayway.com/2012/08/04/a-decimal-to-roman-numeral-converter-in-just... This is the sort of little programming problem that can stop useful work dead in its tracks. Here's my shot at the problem. I think it reads better in that the recursion just deals with the numbers and the Roman numeral strings are mapped latter. It's also a bit more efficient in the way it tests against the Roman "bases" (as I call them). There's no need to retest against a high base once your interim value has gone below that mark. In any case, my version is quite a bit faster than the other solution in my micro-benchmarks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | (ns miner.roman (:require [clojure.test :refer :all])) ;; inspired by ;; http://www.jayway.com/2012/08/04/a-decimal-to-roman-numeral-converter-in-just-a-few-lines/ (def roman-map {1000 "M" 900 "CM" 500 "D" 400 "CD" 100 "C" 90 "XC" 50 "L" 40 "XL" 10 "X" 9 "IX" 5 "V" 4 "IV" 1 "I"}) (def roman-bases (sort > (keys roman-map))) (defn roman-addends [n] {:pre [(< 0 n 4000)]} (loop [n n bases roman-bases addends []] (if (zero? n) addends (let [base (first bases)] (if (>= n base) (recur (- n base) bases (conj addends base)) (recur n (rest bases) addends)))))) (defn roman [n] (apply str (map roman-map (roman-addends n)))) ;; contrib clojure.pprint/cl-format works but is slow (defn roman-cl [n] (clojure.pprint/cl-format nil "~@R" n)) (deftest roman-4k (doseq [n (range 1 4000)] (is (roman-cl n) (roman n)))) |
No comments:
Post a Comment