Jas*_*son 10 lisp algorithm common-lisp
我正在尝试编写一个Common Lisp函数,它将为我提供列表的所有可能排列,仅使用每个元素一次.例如,列表'(1 2 3)将给出输出((1 2 3)(1 3 2)(2 1 3)(2 3 1)(3 1 2)(3 2 1)).
我已经写了一些有用的东西,但它很笨重,它并不总是有用,我甚至都不懂.我不是要求代码,也可能是关于如何思考它的一些指导.我对编写算法知之甚少.
谢谢你,杰森
Vat*_*ine 15
作为一种基本方法,"所有排列"遵循这种递归模式:
all permutations of a list L is: for each element E in L: that element prepended to all permutations of [ L with E removed ]
如果我们认为您的列表中没有重复元素,则应执行以下操作:
(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)))))))
小智 8
这是允许重复元素的答案.代码更加"低迷",因为它不使用循环,缺点是比Rainer Joswig的解决方案更难以理解:
(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))))))
Run Code Online (Sandbox Code Playgroud)
可选的retain参数用于cdring down list,在进入递归之前旋转列表元素.