関数:
リスト 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 のような小さな入力で問題なく動作します。これは、実際にはほとんどの場合に使用されます。ただし、大きな入力で2回続けて呼び出すと、2番目の呼び出しは返されず、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))))
そして、2回目の呼び出しから戻ってくることはありません。なんらかの理由でガベージコレクターに恐ろしいことをしているとしか思えませんが、何がわかりません。誰にもアイデアはありますか?