Prolog では、リスト構造を次のように記述する。
[] ... 空のリスト [a] ... 1つの要素aから成るリスト(長さ1のリスト) [a,b] ... 2つの要素aとbから成るリスト(長さ2のリスト) [a,b,c] ... 3つの要素aとbとcから成るリスト(長さ3のリスト) |
リストの操作は、変数のマッチングによる。
[X] ... 1つの要素から成るリストとマッチ [X|Y] ... 1つ以上の要素から成るリストとマッチ ◎ 長さ1のリストとマッチしたとき、X は先頭の要素、Y は []。 ◎ 長さ2以上のリストとマッチしたとき、X は先頭の要素、 Y は2番目以降の要素から成るリスト [X,Y|Z] ... 2つ以上の要素から成るリストとマッチ ◎ 先頭要素は X、2番目の要素は Y、 3番目以降の要素から成るリストは Z にマッチ |
次のプログラムを入力(Webからコピー)して、動作を確認しよう。ここに示している事実は、今年のF1グランプリの開催国と結果を表している。リストの先頭は、優勝者であり、完走者を順位の番号の昇順に並べている。たとえば、オーストラリア・グランプリでの優勝者は、ハミルトン(ham)、2位は、ハイドフェルド(hei)、3位は、ロズベルグ(ros)である。
優秀者を表す規則は winner_in である。リストの先頭要素ならば、優勝者であるという規則である。
gpx(australia,[ham,hei,ros,alo,kov,nak,bou,rai]). gpx(malaysia, [rai,kub,kov,tru,ham,hei,web,alo,cou,but,piq,fis,bar,ros,dav,sat,nak]). gpx(bahrain, [mas,rai,kub,hei,kov,tru,web,ros,glo,alo,bar,fis,ham,nak,bou,dav,sat,cou,sut]). gpx(spain, [rai,mas,ham,kub,web,but,nak,tru,hei,fis,glo,cou,sat]). gpx(turkey, [mas,ham,rai,kub,hei,alo,web,ros,cou,tru,but,kov,glo,bar,piq,sut,vet]). gpx(monaco, [ham,kub,mas,web,vet,bar,nak,kov,rai,alo,but,glo,tru,hei]). gpx(canada, [kub,hei,cou,glo,mas,tru,bar,vet,kov,ros,but,web,bou]). gpx(france, [mas,rai,tru,kov,kub,web,piq,alo,cou,ham,glo,vet,hei,bar,nak,ros,bou,fis,sut]). winner_in(W,C) :- gpx(C,[W|_]). |
次の質問をしよう。
表彰台に立つことのできるのは、3位までである。そこで、表彰台た立った人のリストを表す規則、gpx_top3_in(L,C) を作成せよ。
Prolog は、再帰的な条件を記述することができる。
リストの中に、指定した要素が存在することを表す規則は、再帰的に宣言できる。
よく使う述語に、
member(X,[X|_]). ← もし、リストの先頭に要素があれば true である。 member(X,[_|L]) :- member(X,L). ← もし、リストの2番目以降のリストに要素があれば true である。 |
完走したこと(完走扱いを含む)を表す規則 gpx_on_course_in(D,C) を作成せよ。D はドライバー名、C はグランプリの開催国である。たとえば、フランスグランプリでは、中嶋(nak)は、完走したので、
完走者のうちビリだった選手と開催国を表す規則 gpx_buttom_on_course_in(D,C) を作成せよ。D はドライバー名、C は国名である。たとえば、フランスグランプリでは、スーティル(sut)がビリだったので
ヒント:リストの最後の要素を表す規則を作れば良い。要素数が1つのリストの場合は、その要素が該当する。要素数が2つ以上のリストの場合、先頭を除くリストにおける最後の要素が該当する。
「ひとり尻取り」のプログラムを作ろう。ルールは次のとおりである:
実行の様子を以下に示す。
?- L=[_,_,_,_], shiritori(L), print_list(L). クマ マントヒヒ ヒトコブラクダ ダックスフント L = [[165, 175, 165, 222], [165, 222, 165, 23, 165, 200, 165|...], [165, 210, 165, 200, 165, 179|...], [165, 192, 165, 195, 165|...]] ; クマ マングース スズメ メダカ L = [[165, 175, 165, 222], [165, 222, 165, 243, 165, 176, 161|...], [165, 185, 165, 186, 165, 225], [165, 225, 165, 192, 165|...]] Yes ?- |
print_list([]). print_list([X|L]):- name(S,X), write(S), nl, print_list(L). |
なお、単語の登録例を以下に示す。実行例を作るために、単語を追加すること。
word("マントヒヒ"). word("ヒトコブラクダ"). word("ダックスフント"). word("クマ"). word("アライグマ"). word("マングース"). word("スズメ"). word("メダカ"). |
カタカナの文字列、つまり、ダブルコーテーションで囲まれた文字列であることに注意せよ。全角のカタカナは、2バイトコードである。たとえば、"マ" は、[165,222] という2バイトで表わされる。
"クマ" = [165, 175, 165, 222] である。W = "クマ" とは、W = [165, 175, 165, 222] なので、先頭の1文字を W から抽出する方法は、W = [X,Y|_] とすれば良い。その結果、X = 165, Y = 175 となる。最後の1文字を W から抽出する方法は、再帰呼出しを使う。もし W が1文字で構成されるならば、W = [A,B] なので、すぐに最後の1文字が得られる。もし、2文字上の場合は、最初の1文字を捨てて、残りの文字における最後の1文字であるならば、全体でも最後の1文字である。
レポートには次のことを記載せよ。