roman numerals revisited

Q&A's, tips, howto's
Locked
eddier
Posts: 289
Joined: Mon Oct 07, 2002 2:48 pm
Location: Blue Mountain College, MS US

roman numerals revisited

Post by eddier »

Lutz,

I've been trying to recode some of my recursive routines to iterative ones. The iterative versions aren't nearly as elegant. For example, recoding a recursive roman numeral conversion to an iterative version looks horrible (below). Looks even worse to maintain, but you're right, it runs significantly faster.

Code: Select all

(define (->roman n)
    (let (s "" v '(100 50 40 10 9 5 4 1))
      (dotimes (i (length v))
        (while (>= n (v i))
          (setq s (append s ('("C" "L" "XL" "X" "IX" "V" "IV" "I") i))
                n (- n (v i)))))
      s))
Am I doning the right thing here? Or, should I be coding in a different way I'm not familiar with? (dotimes (while ick!

Eddie

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

I don't see any improvement except for replacing the repeated append with write-buffer which will be faster for longer bigger n:

Code: Select all

(define (->roman n)
    (let (s "" v '(100 50 40 10 9 5 4 1))
      (dotimes (i (length v))
        (while (>= n (v i))
          (write-buffer s  ('("C" "L" "XL" "X" "IX" "V" "IV" "I") i))
          (setq n (- n (v i))) ))
      s))
I would be interested to see the recursive function too,

Lutz

eddier
Posts: 289
Joined: Mon Oct 07, 2002 2:48 pm
Location: Blue Mountain College, MS US

Post by eddier »

Look at Sam Cox's version.

Here is his algorithm with a few minor changes. Note everything is a pure function with no side effects!

Code: Select all

(define (->roman n)
    (let (roman-a '((100  "C") (99 "IC") (90 "XC") (50  "L") (49 "IL")
                    (40 "XL")  (10  "X") (9 "IX") (5  "V") (4 "IV") (1  "I")))
      
      (define (roman-aux result n pair remaining)
          (roman-aux-2 result n (pair 0) (pair 1) remaining))
      
      (define (roman-aux-2 result n val rep remaining)
          (if (= n 0)  result
              (< n val) (roman-aux result n (remaining 0) (1 remaining))
              (roman-aux-2 (append result rep) (- n val) val rep remaining)))
      
      (roman-aux "" n (roman-a 0) (1 roman-a))))
ps -- My original does not handle 99 and 49 correctly. 99:"IC" and 49:"IL" need to be added to the appropriate lists.


Eddie

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

Ha! never thought about this actualy. Thats not even as simple as we all
"think" it is ;-) I like this..!

Norman.
-- (define? (Cornflakes))

qdn5609
Posts: 1
Joined: Sat Apr 22, 2006 12:00 am

Post by qdn5609 »

Could anyone please help me how to write (roman 2000) in clisp (common lisp). Please Please I got stuck.

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

qdn5609 wrote:Could anyone please help me how to write (roman 2000) in clisp (common lisp). Please Please I got stuck.
http://forums.devshed.com/other-program ... 20899.html

http://paste.lisp.org/display/13733

http://web.cecs.pdx.edu/~mperkows/CLASS ... /ROMAN1.CL

But isn't it built-in to CL's (format) function?

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

There is one on here: http://newlisp.org/index.cgi?roman_numbers_generator

Also accessible from this page: http://newlisp.org/index.cgi?Code_Contributions

This nicely written piece by Sam Cox is easy to understand and translate into any other programming language.

Lutz

Ps: and qdn5609's teacher will be delighted because it is recursive :)

Locked