新元号も発表されたしLisp入門する
Lisp 言語タイトルの通りです。 一度 Lisp をやっておきたいと思っていたところで、ネタを思いついたのでコーディングします。
環境
- Windows 7 64bit
- Steel Bank Common Lisp
処理系は SBCL を使います。 Common Lisp の強力な処理系のひとつです。 機械語にコンパイルされるのでとても速いです。
前に少し流行ったネタですが、元号でこれをやろうと思います。
Javaの講義、試験が「自作関数を作り記述しなさい」って問題だったから
— てくも (@kumiromilk) March 9, 2016
「ズン」「ドコ」のいずれかをランダムで出力し続けて「ズン」「ズン」「ズン」「ズン」「ドコ」の配列が出たら「キ・ヨ・シ!」って出力した後終了って関数作ったら満点で単位貰ってた
汎用ズンドコキヨシ関数をつくる
random-choose
はリストから要素を無作為に 1 つ選び取る関数、take
はリスト先頭からある数を上限に要素を抜き出したリストを返す関数です。
zundoko
が汎用ズンドコキヨシ関数です。
(defun random-choose (ls)
(nth (random (length ls)) ls))
(defun take (ls n)
(if (or (<= n 0) (null ls))
nil
(cons (first ls) (take (rest ls) (1- n)))))
(defun zundoko (words target outs final)
(let ((word (random-choose words))
(order (reverse target)))
(format t word)
(let ((ws (take (cons word outs) (length target))))
(if (equal order ws)
(progn (princ #\newline)
(format t final))
(zundoko words target ws final)))))
ズンドコキヨシ関数は再帰的になっていて、4 つの引数と共に使用します。
(defun zundoko-kiyoshi ()
(zundoko '("ズン" "ドコ") '("ズン" "ズン" "ズン" "ズン" "ドコ") () "キ・ヨ・シ!"))
words
に出力候補の文字列のリストを入れます。
target
に正解の出力順で文字列のリストを入れます。
outs
は前の出力を保持するための引数です。
最初は空リストを渡します。
final
は最後に出力する文字列を入れます。
注意点として出力候補の文字列は他の文字列を作れないような集合である必要があります。
'("ズン" "ドコ" "ズ" "ン")
のようなものを入れると期待していないような結果が出力されます。
昭和平成をランダムに出力して揃ったら令和を出力する
前節の例に倣えば簡単です。 地味すぎるのでテキストを多少装飾しています。
(defun zundoko-reiwa ()
(zundoko '("昭" "和" "平" "成") '("昭" "和" "平" "成") ()
"∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞~% ■■■□ 令 和 □■■■~%∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞"))
これで遊べば新元号にもすぐ慣れるでしょう。
実行ファイルを作ってみる
SBCL は単体実行可能なネイティブバイナリを吐くことができます。
REPL で必要なファイルをロードしたあとに sb-ext:save-lisp-and-die
を実行しましょう。
(load "zundoko.lisp")
(load "zundoko-reiwa.lisp")
(sb-ext:save-lisp-and-die "zundoko-reiwa.exe" :toplevel #'zundoko-reiwa :executable t :application-type :console)
これで配布もバッチリです(ランタイムを含むのでファイルサイズが大きいという欠点はありますが)。 友達に送りつけると良いでしょう。
参考
xyzzy Lisp Programming 入門に非常に良さそうなサイトです。
Land of Lisp 愉快な書籍です。