#lang racket
(require rackunit)
;; 目的 : 整数をローマ数字に変換する。
;; integer->roman : integer -> string
(define (integer->roman n)
(let ((roman-numeral-map '(("M" . 1000)
("CM" . 900)
("D" . 500)
("CD" . 400)
("C" . 100)
("XC" . 90)
("L" . 50)
("XL" . 40)
("X" . 10)
("IX" . 9)
("V" . 5)
("IV" . 4)
("I" . 1))))
(car (foldl (lambda (y x)
(let ((numeral (car y)) (integer (cdr y)))
(let loop ((result (car x)) (n (cdr x)))
(if (< n integer)
`(,result . ,n)
(loop (string-append result numeral) (- n integer))))))
`("" . ,n) roman-numeral-map))))
;; テスト
(check-equal? (integer->roman 1) "I")
(check-equal? (integer->roman 2) "II")
(check-equal? (integer->roman 3) "III")
(check-equal? (integer->roman 4) "IV")
(check-equal? (integer->roman 5) "V")
(check-equal? (integer->roman 6) "VI")
(check-equal? (integer->roman 7) "VII")
(check-equal? (integer->roman 8) "VIII")
(check-equal? (integer->roman 9) "IX")
(check-equal? (integer->roman 10) "X")
(check-equal? (integer->roman 50) "L")
(check-equal? (integer->roman 100) "C")
(check-equal? (integer->roman 500) "D")
(check-equal? (integer->roman 1000) "M")
(check-equal? (integer->roman 31) "XXXI")
(check-equal? (integer->roman 148) "CXLVIII")
(check-equal? (integer->roman 294) "CCXCIV")
(check-equal? (integer->roman 312) "CCCXII")
(check-equal? (integer->roman 421) "CDXXI")
(check-equal? (integer->roman 528) "DXXVIII")
(check-equal? (integer->roman 621) "DCXXI")
(check-equal? (integer->roman 782) "DCCLXXXII")
(check-equal? (integer->roman 870) "DCCCLXX")
(check-equal? (integer->roman 941) "CMXLI")
(check-equal? (integer->roman 1043) "MXLIII")
(check-equal? (integer->roman 1110) "MCX")
(check-equal? (integer->roman 1226) "MCCXXVI")
(check-equal? (integer->roman 1301) "MCCCI")
(check-equal? (integer->roman 1485) "MCDLXXXV")
(check-equal? (integer->roman 1509) "MDIX")
(check-equal? (integer->roman 1607) "MDCVII")
(check-equal? (integer->roman 1754) "MDCCLIV")
(check-equal? (integer->roman 1832) "MDCCCXXXII")
(check-equal? (integer->roman 1993) "MCMXCIII")
(check-equal? (integer->roman 2074) "MMLXXIV")
(check-equal? (integer->roman 2152) "MMCLII")
(check-equal? (integer->roman 2212) "MMCCXII")
(check-equal? (integer->roman 2343) "MMCCCXLIII")
(check-equal? (integer->roman 2499) "MMCDXCIX")
(check-equal? (integer->roman 2574) "MMDLXXIV")
(check-equal? (integer->roman 2646) "MMDCXLVI")
(check-equal? (integer->roman 2723) "MMDCCXXIII")
(check-equal? (integer->roman 2892) "MMDCCCXCII")
(check-equal? (integer->roman 2975) "MMCMLXXV")
(check-equal? (integer->roman 3051) "MMMLI")
(check-equal? (integer->roman 3185) "MMMCLXXXV")
(check-equal? (integer->roman 3250) "MMMCCL")
(check-equal? (integer->roman 3313) "MMMCCCXIII")
(check-equal? (integer->roman 3408) "MMMCDVIII")
(check-equal? (integer->roman 3501) "MMMDI")
(check-equal? (integer->roman 3610) "MMMDCX")
(check-equal? (integer->roman 3743) "MMMDCCXLIII")
(check-equal? (integer->roman 3844) "MMMDCCCXLIV")
(check-equal? (integer->roman 3888) "MMMDCCCLXXXVIII")
(check-equal? (integer->roman 3940) "MMMCMXL")
(check-equal? (integer->roman 3999) "MMMCMXCIX")