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関数だけでこのサイズというのが問題なのだろうか。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください