Lisp算术简化

时间:2015-10-29 01:29:15

标签: lisp

当谈到在lisp编程时,我是一个新手而且不诚实的递归不是我的强项,我的任务是编写一个简化算术方程但不能解决它们的函数。顺便提一下,这是一个学校项目的指导方针。

*写函数简化了如上所述的任何算术表达式(不仅仅是所示的例子)并返回一个新函数,如果可能的话,会进行以下改进:

  1. 乘法子表达式 一个。使用0作为参数,子表达式替换为0:(* 3 5 0) -> 0 湾使用1作为参数,将删除1:(* 1 2 6) -> (* 2 6)。如果只剩下一个参数,那么子表达式将被该参数替换:(* 1 6) -> 6

  2. 加法子表达式 一个。消除任何出现的0:(+ 0 2 7 7) -> (+ 2 7 7)。如果只剩下一个参数,则删除子表达式:(+ 0 7) -> 7

  3. 我的队友和我到目前为止写过:

    (defun simplify (lis)
      (cond
       ((null lis) '())
       ((eq (car lis) '*)
        (cond
         ((not(null (member '0 lis))) 0)
         ((not(null (member '1 lis))) (simplify (remove '1 lis)))
         (t (simplify (cdr lis)))
         )
        )
    
       ((eq (car lis) '+)
        (cond
         (t 0)
         )
        )
       ((listp (car lis)) (cons (simplify (car lis))(simplify (cdr lis))))
       (t (cons (simplify (car lis)) (simplify (cdr lis))))
    
       )
      )
    

    如果您有任何建议,我们无法正常工作!谢谢你也可以忽略我们未完成的+功能。

1 个答案:

答案 0 :(得分:1)

尽量保持功能尽可能简单和短暂总是好的。因此,让我们将此任务分解为多个步骤:

对于+*,都有一个标识元素,您应该从操作中删除它(因为它不会影响结果)。

(defun remove-identity-elements (operands identity)
  (flet ((is-identity (element)
           (equal element identity)))
    (let ((filtered-operands (remove-if #'is-identity operands)))
      (or filtered-operands (list identity)))))

此函数返回已删除标识元素的操作数列表。请注意,我添加了一个检查以避免返回空列表,因此如果filtered-operands是一个空列表(()),or将评估其第二个参数,返回带有标识的列表元素作为单个成员。

对于一个操作,如果只用一个操作数调用它,你应该将它简化为只有一个操作数。这项任务是另一项职能的良好候选人:

(defun compact-single-operand-operation (expression)
  (let ((operands (rest expression)))
    (if (rest operands)
      expression
      (first operands))))

然后可以通过首先从操作数中删除任何标识元素然后最终一起删除操作来处理操作:

(defun simplify-operation (operator operands identity)
  (compact-single-operand-operation
   (cons operator (remove-identity-elements operands identity))))

随着这些功能准备就绪,我们可以接近simplify功能。首先,我们需要涵盖其递归性质:

为了简化操作,您需要首先简化每个操作数,因为它们也可能是复杂的(可简化的)操作。

(defun simplify (expression)
  (if (listp expression)
      (let ((operator (first expression))
            (operands (mapcar #'simplify (rest expression))))
        ;; handle operations
        )
      expression))

我使用mapcar与当前正在定义的函数simplify来获取已经简化的操作数。为了阻止这种递归,我们需要一个基本案例:如果要简化的表达式不是列表,那么我们将其视为"自我评估"并且只是保持不变(这是"否则" if的一部分)。

使用上面的函数simplify-operation来处理操作,虽然我们需要添加一个特殊的检查来处理乘法操作数中可能的0

(cond ((eq operator '+) (simplify-operation '+ operands 0))
      ((eq operator '*)
       (if (find 0 operands)
           0
           (simplify-operation '* operands 1)))
      (t (error "Unsupported operation")))

我还把a live example放在一起玩。