Actually - the original version doesn't work:
user=> (to-roman 7)
"IIIIIII"
Is not quite right...
Whereas your version gives the correct output:
user=> (roman-numeral 7)
"VII"
Your version is very clear. It is not necessary to check if the
remaining value is greater than any of the previously found large
values. For such a trivially small problem space this is a premature
optimisation to worry about. If someone really needed to squeeze CPU
cycles out of a roman number converter I'd be quite surprised!
However for the sake of comparison I thought about a strictly
descending approach:
; order largest to smallest
(def r (sorted-map-by >
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 tim-roman
[n]
(apply str
(loop [todo n, rs r, sofar ()]
(let [roman (first rs)
mag (key roman)
left (rest rs)
times (quot todo mag)
chars (concat sofar (repeat times (val roman)))]
(if (seq left)
(recur (if times (mod todo mag) todo)
left
chars)
chars)))))
Arrrggghh ugly - not worth it!!! I found it frustrating that I
couldn't think of a higher order function for this sort of traversal.
Interestingly I stumbled across this cute way of using subtractors to
avoid hard coding IV etc:
http://rosettacode.org/wiki/Roman_Numerals#Ruby
Regards,
Tim.
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en