BTW, cl-format (my Common Lisp format function for Clojure), supports
the ~...@r directive for converting Arabic to Roman (but nothing to go
the other way around. I didn't spend too much time thinking about
stylistic issues when I wrote it, but if you're interested you can
compare. It's at http://github.com/tomfaulhaber/cl-format.)

On Mar 3, 3:40 am, David Sletten <da...@bosatsu.net> wrote:
> Here's a little toy to practice my basic Clojure skills. I didn't see  
> any similar topic in the archives, so here we go...
>
> This code performs conversions between Roman and Arabic numerals.  
> Roman numerals are represented as strings and Arabic numerals are  
> just integers. Arabic numerals in the range of 1 and 3999 inclusive  
> are allowed. Conventionally, 3999 is the upper limit since the Roman  
> numeral for 5000 (a V with a bar over it) cannot be represented in  
> ASCII (although it exists in Unicode).
>
> The function roman-to-arabic-aux correctly converts any valid Roman  
> numeral. This can be exhaustively tested by comparing the Roman  
> numeral output of Common Lisp's FORMAT function for example (e.g.,  
> (format nil "~...@r" n)). The trick, however, is weeding out bogus  
> strings representing invalid Roman numerals such as IVI, IXV, etc...  
> For this purpose the function "roman?" uses a regular expression I  
> cribbed from Perl's CPAN module Roman.pm (http://search.cpan.org/
> ~chorny/Roman-1.23/lib/Roman.pm).
>
> arabic-to-roman performs the obvious conversion in the other direction.
>
> Incidentally, the "cond" form in roman-to-arabic-aux seems to me  
> harder to read in Clojure than it would be in CL with its additional  
> set of grouping parentheses. When you can't fit both the predicate  
> and the consequent expression on the same line it gets confusing.
>
> I'd appreciate any feedback regarding my Clojure style. Any more  
> natural ways to do things?
>
> Aloha,
> David Sletten
>
> (def roman-values-map {\I 1 \V 5 \X 10 \L 50 \C 100 \D 500 \M 1000})
>
> (defn value [roman]
>    (get roman-values-map (Character/toUpperCase roman)))
>
> (defn roman? [roman-string]
>    (and (not (empty? roman-string))
>         (re-matches
>          #"(?:M{0,3})(?:D?C{0,3}|C[DM])(?:L?X{0,3}|X[LC])(?:V?I{0,3}|I
> [VX])$"
>          roman-string)))
>
> (defn roman-to-arabic-aux [roman-string]
>    (cond (empty? roman-string) 0
>          (empty? (rest roman-string)) (value (first roman-string))
>          (< (value (first roman-string)) (value (second roman-string)))
>          (- (roman-to-arabic-aux (rest roman-string))
>             (value (first roman-string)))
>          :else
>          (+ (value (first roman-string))
>             (roman-to-arabic-aux (rest roman-string)))))
>
> (defn roman-to-arabic [roman-string]
>    (if (roman? roman-string)
>      (roman-to-arabic-aux roman-string)
>      (format "'%s' is not a valid Roman numeral." roman-string)))
>
> (def arabic-values '((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")))
>
> (defn arabic-to-roman
>    ([n] (if (<= 1 n 3999)
>           (apply str (arabic-to-roman n arabic-values))
>           (format "%d cannot be converted." n)))
>    ([n num-list] (cond (empty? num-list) '()
>                        (zero? n) '()
>                        :else (let [[[arabic roman] & tail] num-list]
>                                (if (>= n arabic)
>                                  (cons roman (arabic-to-roman (- n  
> arabic)
>                                                               num-list))
>                                  (arabic-to-roman n tail)))) ))
--~--~---------~--~----~------------~-------~--~----~
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
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