さて、そんなLispとPrologに、それ以降全く触れる事が無かったんですが、どう書く?.orgでソートするコードの生成のお題が出題され、C++やC#であれこれ考えて、行き詰った時にふと、「これ、Prologなら簡単に書けそう。」と思ったんです。「強力なバックトラック機能があれば、前の状態に戻って―――」とか何とか、思ったんです。
で、やってみた訳です。久しぶりのPrologを思い出し(覚えなおし)つつ試行錯誤してみました。他の人のPrologの投稿も参考にしたり、組み込み関数調べたり。
http://ja.doukaku.org/comment/3168/
何とか出来ましたが…あれ?バックトラック一切使ってないし、再帰使ってるだけ…な結果で、簡単に書けたとは言えずとも、簡単な書き方で書けたと思います。
それから、もう水を得た魚で、Prologの未解決問題に挑戦しました(簡単なやつだけw)。いや~、マッチングによる推論というのが何とも面白いです!分かりやすいのを一つ挙げると、仲間はずれの判定で、次のようなもの。
?- classify([1,1,1,1], X).
X = [homo, 1]
?- classify([1,1,2,1], X).
X = [quasi-homo, 1, 2]
?- classify([1,1,2,3], X).
X = [hetero]
X = [homo, 1]
?- classify([1,1,2,1], X).
X = [quasi-homo, 1, 2]
?- classify([1,1,2,3], X).
X = [hetero]
ソースコードは下の通り。
classify([X|Xs], [homo, X]) :- delete(Xs, X, []), !.
classify([X|Xs], [quasi-homo, X, Y]) :- delete(Xs, X, [Y]), !.
classify([Y,X|Xs], [quasi-homo, X, Y]) :- delete(Xs, X, []), !.
classify(_, [hetero]).
classify([X|Xs], [quasi-homo, X, Y]) :- delete(Xs, X, [Y]), !.
classify([Y,X|Xs], [quasi-homo, X, Y]) :- delete(Xs, X, []), !.
classify(_, [hetero]).
解説すると、1行目から順に一致を探します。
- 値Xに続くリストXsから、値Xを削除したリストが空なら [homo]。
- 同様にして、要素Yが一つだけ残っていたら [quasi-homo, X, Y]。
- 値Y,Xに続くリストXsから、値Xを削除して空なら [quasi-homo, X, Y]。
- [hetero]。
覚えたてのPrologで、今度何かパズルを解くプログラムを書きたいと考えてます。