(defparameter mapping '(("I" 1) ("IV" 4) ("V" 5) ("IX" 9) ("X" 10) ("XL" 40) ("L" 50) ("XC" 90) ("C" 100) ("CD" 400) ("D" 500) ("CM" 900) ("M" 1000) ("MA" 4000) ("A" 5000))) (defun get-highest-match (number) (find-if (lambda (x) (<= x number)) mapping :key #'second :from-end t)) ;decimal to roman (defun toroem (number) (if (= number 0) "" (let ((match (get-highest-match number))) (string-concat (car match) (toroem (- number (second match))))))) (defun get-string-match (string) ;sort first to catch IV,IX,XL.... (let ((sorted-mapping (sort mapping #'> :key (lambda (x) (length (car x)))))) (dolist (el sorted-mapping) ;check for long enough 'string' before subseq'ing (if (and (<= (length (car el)) (length string)) (string= (car el) (subseq string 0 (length (car el))))) (return el))))) ;roman to decimal, no error checking (defun todec (string) (let ((match (get-string-match string))) (if (string= "" string) 0 (+ (second match) (todec (subseq string (length (car match))))))))