lisp简化多项式
我正在写一个简化多项式的程序,现在只做加法和乘法 几个小时以来,我一直在用头敲击键盘,我想是时候寻求帮助了lisp简化多项式,lisp,polynomial-math,Lisp,Polynomial Math,我正在写一个简化多项式的程序,现在只做加法和乘法 几个小时以来,我一直在用头敲击键盘,我想是时候寻求帮助了 (defun simplify (lis) (if (eq (car lis) '+) (cons '+ (simplify-addition (cdr lis))) (if (eq (car lis) '*) (cons '* (simplify-multiplication (cdr lis))) )
(defun simplify (lis)
(if (eq (car lis) '+)
(cons '+ (simplify-addition (cdr lis)))
(if (eq (car lis) '*)
(cons '* (simplify-multiplication (cdr lis)))
)
)
)
(defun simplify-addition (lis)
(if (not (null lis))
(if (listp (car lis))
(list (simplify (car lis)) (simplify-addition (cdr lis)))
(if (numberp (car lis))
(if (eq (car lis) 0)
(simplify-addition (cdr lis))
(if (null (cdr lis))
lis
(cons (car lis) (simplify-addition (cdr lis)))
)
)
(if (eq (car lis) '+)
(list (car lis) (simplify-addition (cdr lis)))
(if (eq (car lis) '*)
(list (car lis) (simplify-addition (cdr lis)))
lis
)
)
)
)
)
)
(defun simplify-multiplication (lis)
(if (not (null lis))
(if (listp (car lis))
(if (find 0 (car lis))
0
(list (simplify (car lis)) (simplify-multiplication (cdr lis)))
)
(if (numberp (car lis))
(if (null (cdr lis))
lis
(cons (car lis) (simplify-multiplication (cdr lis)))
)
(if (eq (car lis) '+)
(list (car lis) (simplify-multiplication (cdr lis)))
(if (eq (car lis) '*)
(list (car lis) (simplify-multiplication (cdr lis)))
lis
)
)
)
)
)
)
这就是应该发生的事情:
(simplify ‘(+ x ( + 0 3 ) ( * 1 5 ) ( * ( * x y z ) 0 ) )) --> ( + x 3 5 )
(simplify ‘(* (+ 6 0) (* 1 6 2))) --------------------------------> (* 6 (* 6 2))
但是相反,我要么得到和我发送的相同的多项式,要么得到完全错误的东西
编辑:
我需要的简化是从加法中删除0,以便:
(+ 3 0) --> 3
(+ 4 0 6) --> (+ 4 6)
和零的乘法被移除
(* 6 0 7) --> 0
我只看了
简化乘法
,但这里有一些问题
一般来说,首先要递归地简化,然后再检查特定的常量。(我想这是一种后序遍历。)
其次,我没有看到你在任何地方检查1
,因此我不知道(*15)==>5
应该如何工作
第三,让我们逐步浏览一下(简化“(*(+2 0)3”)
:
(defun simplify-multiplication (lis)
; lis = '((+ 2 0) 3)
(if (not (null lis))
; ==> t
(if (listp (car lis))
; (car lis) = '(+ 2 0), so (listp '(+ 2 0)) ==> t
(if (find 0 (car lis))
; succeeds because '(+ 2 0) contains 0
; this is completely wrong! you're not supposed to check sublists of lis
0
; ... yeah, you just returned 0 just because there was a 0 *somewhere*
(list (simplify (car lis)) (simplify-multiplication (cdr lis)))
)
...
或(简化“(*02))
:
首先,您可能希望稍微改进您的编码风格,使其可读
- 不要在他们自己的行上加括号。这只会浪费空间,毫无帮助
- 不要在域特定代码中使用CAR和CDR。这个领域是数学。使用表达式
。而是使用(运算符arg1 arg2)
和CAR
定义函数CDR
和OPERATOR
,并使用它们参数
- 使用
、CASE
和其他多路条件表达式,而不是嵌套的COND
——如果有用的话IF
- 尝试从域代码中提取数据结构的遍历。使用高阶函数代替递归(
,MAP
,…)REDUCE
(defun operator (expression)
(first expression))
(defun arguments (expression)
(rest expression))
(defun make-expression (operator arguments)
(if (= (length arguments) 1)
(first arguments)
(cons operator arguments)))
(defun is-zero? (expression)
(and (numberp expression)
(= expression 0)))
现在,简化如下:
(defun simplify (expression)
(if (atom expression)
expression
(case (operator expression)
(+ (make-expression '+ (simplify-addition (arguments expression))))
(* (make-expression '* (simplify-multiplication (arguments expression)))))))
(defun simplify-addition (expressions)
(remove-if #'is-zero?
(mapcar #'simplify
(remove-if #'is-zero? expressions))))
(defun simplify-multiplication (expressions)
(if (member-if #'is-zero? expressions)
(list 0)
(let ((expressions1 (mapcar #'simplify expressions)))
(if (member-if #'is-zero? expressions1)
(list 0)
expressions1))))
看,代码的可读性有多高?不再有CAR
,LIS
,CDR
。递归调用的意图也更容易理解
它仍然不是最优的,但它应该会让你前进。+1对于你的缩进风格,-1对于你没有说你得到了什么结果,所以你应该只简化一个级别?我这样问是因为在你的第二个例子中,结果可以简化为72,但你只需要到(*6(*6 2))我更新了问题,更具体地说明了函数应该做什么。请学习如何。如果你已经阅读了整个内容,你会看到当它遇到一个列表元素时,它将其发送回simplify函数,simplify函数读取第一个字符(+or),然后将其发送到相应的函数,因此在您的第一个示例中,一旦它获得第一个元素列表,它将看到这是一个加法,并将其发送到那里。此外,在乘法函数中,如果列表中的任何地方都有一个零,我确实希望返回0,因为(0x)-->0如果您阅读了我的注释,您会发现在我的示例中它不会返回到
simplify
。我同意如果参数中有0,您确实希望返回0,但代码没有这样做。相反,如果其中一个参数是另一个列表,并且内部列表包含0,则返回0。如果我的评论听起来很粗鲁,那么很抱歉,这不是我的本意,您的评论非常有用,并使我识别了一些错误。
(defun simplify (expression)
(if (atom expression)
expression
(case (operator expression)
(+ (make-expression '+ (simplify-addition (arguments expression))))
(* (make-expression '* (simplify-multiplication (arguments expression)))))))
(defun simplify-addition (expressions)
(remove-if #'is-zero?
(mapcar #'simplify
(remove-if #'is-zero? expressions))))
(defun simplify-multiplication (expressions)
(if (member-if #'is-zero? expressions)
(list 0)
(let ((expressions1 (mapcar #'simplify expressions)))
(if (member-if #'is-zero? expressions1)
(list 0)
expressions1))))