1

基本上我需要在下面将这个属性表示为 lisp 中的一个函数

(p and q) or (r and t) = (p or r) and (p or t) and (q or r) and (q or t)

函数distribute-or (fbf) 将类型的公式作为参数

(or (and a b) c ) 并将其转化为(and (or a c) (or b c))

但是,问题是你不知道 or-formula 可以有多少个参数,哪些是字母,哪些是字母的连词。它可以是以下任何示例

(or a b)保持原样

(or a b c (and d e f)应该变成(and (or a b c d) (or a b c e) (or a b c f) (or (and a b) (and d e))哪个交(and (or a d) (or a e) (or b d) (or b e))

只有当“或”有 2 个参数时,我才能设计一个函数,但如果它有更多参数,我不知道该怎么做。

4

2 回答 2

0

所以,你已经有了一个f可以转换((a b) (c d))成的函数((a c) (a d) (b c) (b d))(我省略了ands 和ors)。

您需要一个可以转换((a b) (c d) (e f))((a c e) (a c f) (a d e) (a d f) (b c e) (b c f) (b d e) (b d f)).

这似乎是reduce:的一个明显案例(reduce #'f mylist)

于 2013-02-13T17:58:45.473 回答
0

由于你没有编写你的版本distribute-or,我建议使用这个变体,它需要任何长度的 fbf,但不能深入工作。

(defun dekart-product (sets)
  (if (null sets)
      (list '())
      (let ((prod (dekart-product (cdr sets))))
        (mapcan #'(lambda (lst) 
                    (mapcar #'(lambda (el) (cons el lst))
                            (car sets)))
                prod))))

(defun collect-ands (l)
  (mapcar #'(lambda (el)
              (if (and (consp el)
                       (eq 'and (car el)))
                  (cdr el)
                  (list el)))
          l))

(defun distribute-or (fbf)
  (if (and (consp fbf)
           (eq 'or (car fbf)))
      (cons 'and (mapcar #'(lambda (lst) (cons 'or lst))
                         (dekart-product
                                (collect-ands (cdr fbf)))))
      fbf))

结果是:

(distribute-or '(or a b c (and d e f)))
;=> (AND (OR A B C D) (OR A B C E) (OR A B C F))

它以一种简单的方式工作:

  • 将所有参数和表达式收集到集合中: (or (and a b c) (and e f) g)-->((a b c) (e f) (g))
  • 然后制作所有收集到的集合的 dekart-product(换句话说,笛卡尔积)
  • 并形成输出表达式,只需添加'orand 'and,其中需要
于 2013-02-13T20:05:13.497 回答