Lisp排列功能 - 我在这里做错了什么?

时间:2013-09-14 19:57:38

标签: recursion lisp common-lisp

我想尝试一些Common Lisp。我已经习惯了大括号的命令式语言,而且我仍然无法绕过Lisp风格的思维和语法。

下面是我正在尝试编写的排列函数。它目前已经破裂。

如果我用

运行此功能
(permutations '(1 2 3))

我可以在标有“和此处”的断点处看到,在此点生成诸如(2 3),(3 2),(1 3)之类的列表。但是然后通过在SLIME中运行跟踪,我看到置换函数在该调用之后返回(2),(3)和(1)(在lisp中的第一项)。顶级函数然后返回nil(我也不明白)。

(defun permutations (coll)
(if (= 1 (length coll))
 (print (list (first coll)))
  (loop for el in coll do
   (map 'list #'(lambda (combos) 
          (if 
               (break "you got here with arguments ~:S." (listp combos))
               (cons el combos)
               (break "and here: ~:S " (list el combos))))

    (permutations (remove el coll))
    ))))

我在这里做错了什么?提前感谢您的帮助。

编辑: 这是我在更改功能以回应jlahd的评论后所拥有的。这回来了 (((1((2 3)))(1((3 2))))((2((1 3)))(2((3 1))))((3((1 2)) )(3((2 1)))))用原始例子调用时。还没有想出如何修复嵌套列表的事情。

(defun permutations (coll)
  (if (= 1 (length coll))
      (print (list (first coll)))
      (loop for el in coll collect
           (map 'list #'(lambda (combos) 
                          (list el combos))    
                (permutations (remove el coll))
                ))))

编辑: 好的,谢谢大家的帮助!以下是我对Rörd和wxvxw的评论之后的看法。 运行并返回((1 2 .3)(1 3.2)(2 1.3)(2 3.1)(3 1.2)(3 2.1))。我不确定这里的“点对”符号与普通列表相比意味着什么,但除此之外这看起来还不错。

(defun permutations (coll)
  (if (not (cdr coll))
      (list (first coll))
      (loop for el in coll nconc
           (mapcar #'(lambda (combos) 
                       (cons el combos))    
                   (permutations (remove el coll))
                   ))))

1 个答案:

答案 0 :(得分:2)

您正在放弃在loop中收集的所有数据。将do更改为collect,您就更远了。