Meta-Loopless Sorts
ソートするコードの生成(http://ja.doukaku.org/63/)
今どう書く.orgにアクセスできなくなってるみたいです。
Meta-Loopless Sortsの改題です.
n個の整数をソートするプログラムを生成するプログラム gensort を書いて下さい.条件は以下のとおり
1. 生成するプログラム,生成されたプログラムは同じ言語にして下さい.
2. 生成したプログラムはファイルに書き込んでください.
3. 生成されたプログラムでは最初に n 個の整数を読み込んで, n個の変数を初期化してください.「可能なら」変数名は,アルファベット 一文字で a,b,c … の順で使ってください.n = 5 なら 変数は a, b, c, d, e です.
4. 生成されたプログラムでは,if 文あるいは if 式で2つの変数を比較して いって,変数の順が確定したら,その順で変数の値を出力するようにして 下さい.
5. 生成される側のプログラムでのアルゴリズムやデータ構造を工夫する問題では ありません :)
出力プログラム例のPascalのプログラムが、大小関係を < だけで比較してるということは、引数のリストに同じ数値は含まれないということですかね。あと、「生成されたプログラムでは,if 文あるいは if 式で2つの変数を比較して いって」といことでしたが、下のコードでは一気に比較してます。反則かも。
;組合せを生成する関数(defun combination (lst)(let (combi)(labels ((rec (l acc)(if (null l)(push acc combi)(loop for e in l collect (rec (remove e l) (cons e acc))))))(rec lst nil) combi)));ソート関数生成関数; ソート対象は、同じ値は含まれないものとする。(defun gensort-func (n)(if (not (< 0 n 27)) (error "out of range. n is between 1 and 26."))(let* ((arg-lst (loop for i from 1 to n collect (intern (string (code-char (+ 64 i))))))(combinations (combination arg-lst)))`(defun my-sort ,arg-lst ,@(loop for combi in combinations collect `(if (< ,@combi)(format t "~{~d~^,~}~%" (list ,@combi)))))));my-sort.lispへのソート関数の保存(defun gensort (n)(with-open-file (s "my-sort.lisp" :direction :output)(prin1 (gensort-func n) s)))
計測用コード
;計測(loop for lst in '((3 4)(1 2 3)(3 4 5 6)(6 2 5 1 9)(8 3 2 5 1 3)(4 1 9 2 8 5 3)(9 1 8 2 7 3 6 5)(0 9 1 8 2 7 3 6 5)(0 9 1 8 2 7 3 6 5 10))do(let ((len (length lst)))(format t "=== ~d ~a===~%" len lst)(format t "--gensort~%")(time (gensort len))(format t "--load function~%")(time (load "my-sort.lisp"))(format t "--exec~%")(time (apply #'my-sort lst))))
defmacroで関数を生成して、生成された関数を呼出すのが普通なので、生成した関数を一度ファイルに保存するというのが、lisp的には奇妙な処理になってしまっています。
で、clisp上での実行結果(コンパイル済)は、途中で、「*** – Program stack overflow. RESET」となりました。要素数8の時の “my-sort.lisp” のロード中にstack overflowが出ました。この時点で、my-sort.lispの中身は、40,320行(2,985,984バイト)でした。1関数だけでこのサイズというのが問題なのだろうか。