使用lisp简化简单布尔表达式

使用lisp简化简单布尔表达式,lisp,boolean-expression,Lisp,Boolean Expression,我有一个简单的布尔表达式,以lisp列表的形式呈现,如下所示: '(或0(和A1 A2)) 前面的列表是((A1和A2)或0)的表示 无论如何,我正在写一个函数来简化这个表达式。。 例如: 像这样调用函数“reduce”: (减少’(或0(和A1-A2))) 会让步 (A1和A2) 我首先尝试创建基本规则,所以我定义了 以下标识: (和1s)==S (或0秒)=S (和0 S)==0 (或1s)==1 (非O)==1 (不是1)==0* 我想定义6个函数,每个规则一个,然后 在包装器中逐个调用它

我有一个简单的布尔表达式,以lisp列表的形式呈现,如下所示: '(或0(和A1 A2))

前面的列表是((A1和A2)或0)的表示

无论如何,我正在写一个函数来简化这个表达式。。 例如:

像这样调用函数“reduce”:

(减少’(或0(和A1-A2)))

会让步

(A1和A2)

我首先尝试创建基本规则,所以我定义了 以下标识

(和1s)==S

(或0秒)=S

(和0 S)==0

(或1s)==1

(非O)==1

(不是1)==0*

我想定义6个函数,每个规则一个,然后
在包装器中逐个调用它们,我不熟悉lisp,所以我不知道如何实现它,我曾经用java实现过,但我不知道如何使用lisp的语法来处理此类问题,所以请帮助我。

我终于想出了这个解决方案

(defun simplify (EXPR)
  (simplify-expr NIL EXPR))

(defun simplify-expr (EXPR1 EXPR2)
  (cond 
   ((or (atom EXPR2) (equal EXPR1 EXPR2)) EXPR2)
   (T (simplify-expr EXPR2 (simplify-boolean-expr EXPR2)))))

(defun simplify-boolean-expr (EXPR)
  (cond 
   ((and (equal (first EXPR) `and) (>= (length EXPR) 3)) 
    (simplify-and-expr (rest EXPR)))
   ((and (equal (first EXPR) `or) (>= (length EXPR) 3)) 
    (simplify-or-expr (rest EXPR)))
   ((and (equal (first EXPR) `not) (= (length EXPR) 2)) 
    (simplify-not-expr (rest EXPR)))
   (T 
    (error "~S is not a valid circuit descriptor expression or has an unknown operator." EXPR))))

(defun simplify-and-expr (EXPR)
  (let ((SIMPLIFIED_EXPR (remove `T (remove-duplicates EXPR))))
    (cond 
     ((null SIMPLIFIED_EXPR) `T)
     ((member `NIL SIMPLIFIED_EXPR) `NIL)
     ((null (second SIMPLIFIED_EXPR)) (first SIMPLIFIED_EXPR))
     (T (cons `and (simplify-operand SIMPLIFIED_EXPR))))))

(defun simplify-or-expr (EXPR)
  (let ((SIMPLIFIED_EXPR (remove `NIL (remove-duplicates EXPR))))
    (cond
     ((null SIMPLIFIED_EXPR) `NIL)
     ((member `T SIMPLIFIED_EXPR) `T)
     ((null (second SIMPLIFIED_EXPR)) (first SIMPLIFIED_EXPR))
     (T (cons `or (simplify-operand SIMPLIFIED_EXPR))))))

(defun simplify-not-expr (EXPR)
  (cond 
   ((equal (first EXPR) `NIL) `T)
   ((equal (first EXPR) `T) `NIL)
   ((and (listp (first EXPR)) (equal (first (first EXPR)) `not)) 
    (first (rest (first EXPR))))
   (T (cons `not (simplify-operand EXPR)))))

(defun simplify-operand (OPERAND_LIST)
  (cond 
   ((null OPERAND_LIST) NIL)
   ((atom (first OPERAND_LIST)) 
    (cons (first OPERAND_LIST) (simplify-operand (rest OPERAND_LIST))))
   (T 
    (cons (simplify-expr NIL (first OPERAND_LIST)) (simplify-operand (rest OPERAND_LIST))))))

(0,1)取(nil,T)并减少任何布尔表达式,我尝试过,效果很好。

考虑到解决方案的复杂性,下面是我的实现,它更短,可读性更强:

(defun reduc (exp)
  (if (atom exp) 
      exp
      (flet ((helper (op args n) ; and and or is nearly the same code so we factor it out
               (let ((newargs (remove n args)) (cn (- 1 n)))
                 (cond
                  ((null newargs) n)
                  ((some (lambda (e) (eql cn e)) newargs) cn)
                  ((null (cdr newargs)) (car newargs))
                  ((cons op newargs))))))
        (let ((op (car exp)) (args (mapcar #'reduc (cdr exp))))
          (ecase op
            ((not) (if (= 1 (length args))
                       (let ((arg1 (car args)))
                         (if (and (numberp arg1) (<= 0 arg1 1)) (- 1 arg1) exp))
                       (error "'not' must have exactly one parameter")))
            ((and) (helper op args 1))
            ((or)  (helper op args 0)))))))

你应该自己努力解决那个问题。。。让别人为你编写代码无助于你学习编程。我的朋友,我对lisp非常陌生,我需要线索,我试图定义基本规则,但我的问题是如何在函数中使用它们,如何使用lisp实现这一点,这就是我想要的……你说得对,但这是我第一次使用lisp和prologue,我需要了解这些解决方案。。我在互联网上找不到任何关于如何在递归列表编程环境(如lisp)中计算布尔表达式的来源,我在这方面和前面的问题上都做了很多工作,但lisp似乎是如此不同,调试起来也很困难我的朋友这里有一本很棒的书可以免费下载,这将教你口齿不清,并向你展示许多可以学习的例子。读完这本书后,解决问题将是完全自然的:你搜索这些资源是如此正确,幸运的是你的搜索已经结束。你已经找到了你需要阅读的书。我现在就查一下。谢谢我的朋友。这取决于你使用的是哪种Lisp。如果是球拍,你就有了。如果它是公共Lisp,您将不得不编写更多复杂的代码,或者使用外部库,例如。不客气。如果他们完全回答你的问题,请考虑接受我的回答。当然,我是新来的,所以,我只需要得到足够的声誉来提高投票/下限投票的答案。我不是在谈论上/下投票,而是通过点击复选标记。这向更广泛的社区表明,你已经找到了一个解决方案,并给回答者和你自己带来了一些声誉。没有义务这样做。
? (reduc '(OR 0 (AND A1 A2))) 
(AND A1 A2)
? (reduc '(OR 0 (AND A1 1 A2)))
(AND A1 A2)
? (reduc '(or ERROR (not 0)))
1
? (reduc '(AND ERROR (not 0)))
ERROR
? (reduc '(OR 0 (AND A1 0))) 
0
? (reduc '(OR 0 (AND A1 1))) 
A1