Некоторые начальные примечания.
- Задавая вопрос, который включает в себя реализацию алгоритма опишите алгоритм : нелегко угадать, что вы хотите, основываясь на одном примере (ниже я сделал два предположения).
- Я полагаю, что вы уже писали на Python ранее, так как в вашем коде присутствуют значительные признаки «Python Braindamage» (обратите внимание, что это комментарий о Python, который я потратил годымоей жизни, а не о ваших способностях).В частности:
- Lisp не путает формы, которые создают новые привязки (переменные) с присваиванием, как это делает Python.Вы не создаете новую привязку в функции с помощью
setq
, вы создаете ее с помощью некоторой формы привязки, такой как let
; - Вы не добавляете новые элементы в конец списка с помощью
append
вы создаете новый список, в который добавляются новые элементы, и поскольку списки являются связанными списками, а не массивами переменной длины при перетаскивании, append
занимает время, пропорциональное длине списка.
- Но в одном отношении ваш код игнорирует важный урок Python: все эти маркеры закрытия групп не имеют значения для любого, кто читает код, и вам не следует заполнять строки маркерами закрытия (или открытия) одной группы,Они просто шум, который затрудняет чтение кода.На самом деле в Python они настолько невидимы, что их вообще не существует.Это одна из вещей, которые Python понял правильно.
Как говорится, здесь есть три версии того, что я думаю вы хотите: первая реализует то, о чем я думаюпоследовательный алгоритм, второй реализует то, что, я думаю, вам может понадобиться, а последний - абстрагирует тест завершения и может выполнять любой (или любой другой)).
(defun make-permuted-tree (l)
;; this builds the tree all the way down
(if (null l)
'()
(loop for e in l
collect (cons e (make-permuted-tree (remove e l))))))
(defun make-permuted-tree/strange (l)
;; this stops before the end
(if (null (rest l))
l
(loop for e in l
collect (cons e (make-permuted-tree/strange (remove e l))))))
(defun make-permuted-tree/general (l &key (base-test (lambda (b)
(null b))))
;; this stops where you want it to, which by default is at the end
(labels ((make-permuted-tree (lt)
(if (funcall base-test lt)
lt
(loop for e in lt
collect (cons e (make-permuted-tree (remove e lt)))))))
(make-permuted-tree l)))
В качестве примеров этого:
> (make-permuted-tree/strange '(1 2 3))
((1 (2 3) (3 2)) (2 (1 3) (3 1)) (3 (1 2) (2 1)))
> (make-permuted-tree '(1 2 3))
((1 (2 (3)) (3 (2))) (2 (1 (3)) (3 (1))) (3 (1 (2)) (2 (1))))
> (make-permuted-tree/general '(1 2 3))
((1 (2 (3)) (3 (2))) (2 (1 (3)) (3 (1))) (3 (1 (2)) (2 (1))))
> (make-permuted-tree/general '(1 2 3) :base-test (lambda (b)
(null (rest b))))
((1 (2 3) (3 2)) (2 (1 3) (3 1)) (3 (1 2) (2 1)))