mapcar lisp的替代品

时间:2016-06-24 19:06:59

标签: lisp powerset

我需要为powerset写一个递归函数,但是我不能使用mapcar,loop。

到目前为止,这是我的代码:

(defun parts (L)
  (cond 
    ((null L)'(nil))    
    (T
      (let ((PXs (parts (cdr L))))
        (append PXs (add(car L) PXs))
      )
    )   
  )
)

(defun add (E Cs)
  (cond
    (
    (null (cdr Cs))
        (list(cons E Cs))
    )
    (T 
        (append(list(cons E (list (car Cs)))) (addE (cdr Cs)))          
    )   
  )
)

但(部分(' 1 2 3))的结果是:

(NIL (3 NIL) (2 NIL) (2 (3 NIL)) (1 NIL) (1 (3 NIL)) (1 (2 NIL)) (1 (2 (3 NIL))))

我找到了这个方法

(defun powerset (list)
   (let ((x (car list)))
     (if x
       (let ((p (powerset (cdr list))))
         (append p (mapcar (lambda (list) (cons x list)) p)))
      '(()))))

(powerset(' 1 2 3))的结果是:

(NIL (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))

但是我无法使用mapcar,我在代码中找不到问题,是否有替代功能mapcar?

2 个答案:

答案 0 :(得分:3)

这是一个可能的解决方案:

(defun parts (l)
  (if (null l)
      '(())
      (add (car l) (parts (cdr l)))))

(defun add (x pset)
  (if (null pset)
      nil
      (cons (car pset)
            (cons (cons x (car pset))
                  (add x (cdr pset))))))

(parts '(1 2 3))  ;   =>  (NIL (1) (2) (1 2) (3) (1 3) (2 3) (1 2 3))

函数add以这种方式将元素x添加到powerset:

  1. 如果powerset为空,则无需添加任何内容;
  2. 否则,通过在powerset的所有列表中插入或不插入元素来获得新的powerset,因此通过复制其列表的数量来获得。
  3. 函数parts递归地构建列表的powerset,通过将其中一个元素添加到由包含空列表的列表(空集的powerset)构成的powerset中。

答案 1 :(得分:2)

问题:我们不能使用:

 (mapcar (lambda (list) (cons x list)) p)

解决方案:

 (pairlis (make-list (length p) :initial-element x) p)

也就是说,我们制作一个与p长度相同的列表,其中包含x值的重复。然后我们" zip-cons" p使用pairlis

进行此操作
 ;; understanding pairlis:
 (pairlis '(a b c) '(1 2 3)) ->  { either: ((a . 1) (b . 2) (c . 3))
                                 { or:     ((c . 3) (b . 2) (a . 1))

pairlis,只给出两个参数(没有 alist ),实际上是(mapcar #'cons list1 list2)伪装,list1和{{1}加上限制必须具有相同的长度,结果可以是向前或向后的顺序。