Validation LISP-检查罗马数字转换器是否存在有效的罗马数字

Validation LISP-检查罗马数字转换器是否存在有效的罗马数字,validation,lisp,common-lisp,Validation,Lisp,Common Lisp,我有一个lisp程序,可以将罗马数字转换成十进制形式。它对于有效的输入非常有效,但是我不确定如何检查输入是否是有效的罗马数字。例如,当前当给定一个无效输入(“MIM”)时,它仍然试图错误地转换它。我需要它返回一条错误消息 (defun mapRomanToDecimal (chars nums string) (loop as char across string as i = (position char chars) collect (and i (nth

我有一个lisp程序,可以将罗马数字转换成十进制形式。它对于有效的输入非常有效,但是我不确定如何检查输入是否是有效的罗马数字。例如,当前当给定一个无效输入(“MIM”)时,它仍然试图错误地转换它。我需要它返回一条错误消息

(defun mapRomanToDecimal (chars nums string)
  (loop as char across string
        as i = (position char chars)
        collect (and i (nth i nums))))

(defun parseThroughRoman (R)
  (loop with nums = (mapRomanToDecimal "IVXLCDM" '(1 5 10 50 100 500 1000) R)
    as (A B) on nums if A sum (if (and B (< A B)) (- A) A)))

(defun romanToDecimal (RomanNumeral)
    (format t "~d~%" (parseThroughRoman (numlist-to-string RomanNumeral))))

(defun numlist-to-string (lst)
  (when lst
     (concatenate 'string 
             (write-to-string (car lst)) (numlist-to-string (cdr lst)))))


(romanToDecimal '(C D V)) -> 405
(romanToDecimal '(M I M)) -> 1999
(定义mapRomanToDecimal(chars nums字符串)
(在字符串中以字符形式循环)
as i=(位置字符)
收集(和i(n个nums)))
(通过Hroman(R)卸载)
(带nums的循环=(mapRomanToDecimal“IVXLCDM”'(1 5 10 50 100 500 1000)R)
如果一个和(如果(和B(405
(罗马法典)(M I M))->1999年

关于风格的一点

  • 数据类型转换通常是不必要的
  • 代码可以很容易地变得更通用
例如:

(defvar *roman-chars* "IVXLCDM")
(defvar *roman-nums*  '(1 5 10 50 100 500 1000))

(defun roman-numeral-to-decimal (roman-numeral)
  (let ((i (position (coerce roman-numeral 'character) *roman-chars*)))
    (and i (nth i *roman-nums*))))

(defun map-roman-numerals-to-decimal (roman-numerals)
  (map 'list #'roman-numeral-to-decimal roman-numerals))

(defun roman-to-decimal (roman)
  (loop as (A B) on (map-roman-numerals-to-decimal roman)
        if A sum (if (and B (< A B)) (- A) A)))

(1) 请注意,
“MIM”
”(M I M)
是不同的值(字符串与列表)。(2) 您需要明确指定输入有效与否的规则。然后您就可以添加支票了。(3) 样式:破折号分隔的名称,请不要用camelCase。我知道MCM在1900年有效,那么为什么MIM在1999年无效?还要注意,Common Lisp的格式已经可以了。
CL-USER 20 > (roman-to-decimal '(C D V))
405

CL-USER 21 > (roman-to-decimal '("C" "D" "V"))
405

CL-USER 22 > (roman-to-decimal '(#\C #\D #\V))
405

CL-USER 23 > (roman-to-decimal "CDV")
405

CL-USER 24 > (roman-to-decimal #(c d v))
405