使用lisp简化简单布尔表达式
我有一个简单的布尔表达式,以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简化简单布尔表达式,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,所以我不知道如何实现它,我曾经用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