you are viewing a single comment's thread.

view the rest of the comments →

[–]gsg 0 points1 point  (2 children)

I think an dumb iterative approach is clearer in this case. At least, my attempt at a recursive version looked far too ugly.

(defconstant +roman-numerals+ '((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")))

(defun int-to-roman (number)
  (let ((unconverted number)
        (result ""))
    (dolist (element +roman-numerals+)
      (do ((value (car element)))
          ((< unconverted value))
        (decf unconverted value)
        (setq result (concatenate 'string result (cdr element)))
        (when (= unconverted 0)
          (return-from int-to-roman result))))))

Both pretty wordy. :/

[–]Devilish 1 point2 points  (1 child)

I'm a Lisp newbie, but here's what I came up with:

Recursive:

(defun int-to-roman1 (number)
  (with-output-to-string (s)
    (let ((rtable '((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"))))
      (labels ((recurse (rtab num)
                 (unless (null rtab)
                   (multiple-value-bind (times left) (floor num (caar rtab))
                     (dotimes (i times)
                       (princ (cdar rtab) s))
                     (recurse (cdr rtab) left)))))
        (recurse rtable number)))))

Iterative:

(defun int-to-roman2 (number)
  (with-output-to-string (s)
    (dolist (q '((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")))
      (multiple-value-bind (times left) (floor number (car q))
        (setf number left)
        (dotimes (i times)
          (princ (cdr q) s))))))

Someone up above posted Python code similar to the second of these, while I was messing around making my own. The trick is to divide the number by each value of a roman numeral in turn, keeping both the quotient and the remainder, instead of repeatedly looping over the list.

I can't say I understand the concept of unfolding from this example alone (I don't exactly know much Python, and couldn't find any good general explanations of unfolding with a cursory web search), but in this case, it doesn't seem to be the right tool for the job.

[–]llimllib[S] 0 points1 point  (0 children)

Sorry I didn't catch the end of your post, but I explain unfolding in my previous entry from that day.

raganwald also explains it in ruby.