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))))