How can I get all possible permutations of a list with Common Lisp?

▼魔方 西西 提交于 2019-12-03 06:11:17
Vatine

As a basic approach, "all permutations" follow this recursive pattern:

  all permutations of a list L is:
    for each element E in L:
      that element prepended to all permutations of [ L with E removed ]

If we take as given that you have no duplicate elements in your list, the following should do:

(defun all-permutations (list)
  (cond ((null list) nil)
        ((null (cdr list)) (list list))
        (t (loop for element in list
             append (mapcar (lambda (l) (cons element l))
                            (all-permutations (remove element list)))))))

Here is the answer which allows repeated elements. The code is even more "lispish" as it doesn't use loop, with the disadvantage of being less comprehensible than Rainer Joswig's solution:

(defun all-permutations (lst &optional (remain lst))
  (cond ((null remain) nil)
        ((null (rest lst)) (list lst))
        (t (append
            (mapcar (lambda (l) (cons (first lst) l))
                    (all-permutations (rest lst)))
            (all-permutations (append (rest lst) (list (first lst))) (rest remain))))))

The optional remain argument is used for cdring down the list, rotating the list elements before entering the recursion.

Walk through your list, selecting each element in turn. That element will be the first element of your current permutation.

Cons that element to all permutations of the remaining elements.

Ken

I'm not sure if your question is about Common Lisp, or about the algorithm.

There are similar problems (and solutions) for other languages here, e.g., Python. Python can often be translated into Common Lisp virtually line-for-line, so pick one and port it? :-)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!