ローマ数字を扱う - lisp-cookbook-ja/common-lisp GitHub Wiki

数値

ローマ数字を扱う

アラビア数字からローマ数字への変換は、format関数が使えます。 format関数は通常の書式と古い書式をオプションで切り換えることが可能です。

アラビア数字→ローマ数字(文字列)

(mapcar (lambda (x) (format nil "~@R" x))
        '(1 2 3 4 500 999))
;=> ("I" "II" "III" "IV" "D" "CMXCIX")

;; 古い書式
(mapcar (lambda (x) (format nil "~@:R" x))
        '(1 2 3 4 500 999))
;=> ("I" "II" "III" "IIII" "D" "DCCCCLXXXXVIIII")

ローマ数字からアラビア数字へ変換するための関数はANSI CLには含まれていませんので自作するかライブラリを利用することになります。

ローマ数字(文字列)→アラビア数字

;; 素朴な実装 FIXME
(defun roman-to-arabic (str)
  (let ((nums (nreverse (map 'list #'*roman-to-arabic str))))
    (reduce #'+ (mapcar (lambda (x y) (if (> x y) (- y) y))
                        (cons 0 nums)
                        nums))))

(defun *roman-to-arabic (char)
  (case char
    ((#\i #\I) 1)
    ((#\v #\V) 5)
    ((#\x #\X) 10)
    ((#\l #\L) 50)
    ((#\c #\C) 100)
    ((#\d #\D) 500)
    ((#\m #\M) 1000)))

;; 動作
(mapcar #'roman-to-arabic
        '("I" "II" "III" "IV" "D" "CMXCIX"))
;=> (1 2 3 4 500 999)

;; 古い書式
(mapcar #'roman-to-arabic
        '("I" "II" "III" "IIII" "D" "DCCCCLXXXXVIIII"))
;=> (1 2 3 4 500 999)