2007年9月27日木曜日

Prologが面白い

 大学の2回生の頃に、プログラミング言語の授業で扱った言語が、LispとPrologでした。今時、そんな古典的な言語をと思われるかもしれないが(と いうか思ってたんですが)、授業を受けてみると、当時C言語とC++しか知らなかった私には、もの凄く新鮮で、他の学生との温度差を感じつつ、毎回の授業 が楽しかった思い出があります。
 さて、そんな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]

ソースコードは下の通り。
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]).

解説すると、1行目から順に一致を探します。
  1. 値Xに続くリストXsから、値Xを削除したリストが空なら [homo]。
  2. 同様にして、要素Yが一つだけ残っていたら [quasi-homo, X, Y]。
  3. 値Y,Xに続くリストXsから、値Xを削除して空なら [quasi-homo, X, Y]。
  4. [hetero]。
第一引数と尾部分がマッチすれば、第二引数が決まってるといった感じです。

覚えたてのPrologで、今度何かパズルを解くプログラムを書きたいと考えてます。

0 件のコメント: