功能:
给定一个列表 lst 返回列表内容的所有排列,长度正好为 k,如果未提供,则默认为列表长度。
(defun permute (lst &optional (k (length lst)))
(if (= k 1)
(mapcar #'list lst)
(loop for item in lst nconcing
(mapcar (lambda (x) (cons item x))
(permute (remove-if (lambda (x) (eq x item)) lst)
(1- k))))))
问题:我在连接到 sbcl 的 emacs 中使用 SLIME,我还没有做太多的自定义。该函数适用于较小的输入,例如 lst = '(1 2 3 4 5 6 7 8) k = 3,这在实践中主要用于。但是,当我连续两次使用大输入调用它时,第二次调用永远不会返回,并且 sbcl 甚至不会出现在顶部。这些是 REPL 的结果:
CL-USER> (time (nth (1- 1000000) (permute '(0 1 2 3 4 5 6 7 8 9))))
Evaluation took:
12.263 seconds of real time
12.166150 seconds of total run time (10.705372 user, 1.460778 system)
[ Run times consist of 9.331 seconds GC time, and 2.836 seconds non-GC time. ]
99.21% CPU
27,105,349,193 processor cycles
930,080,016 bytes consed
(2 7 8 3 9 1 5 4 6 0)
CL-USER> (time (nth (1- 1000000) (permute '(0 1 2 3 4 5 6 7 8 9))))
它永远不会从第二个电话回来。我只能猜测出于某种原因我对垃圾收集器做了一些可怕的事情,但我看不到是什么。有没有人有任何想法?