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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to