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,[but,bar,tru,glo,alo,ros,bue,bou,sut,hei,fis,web,vet,kub,rai]). gpx(malaysia, [but,hei,glo,tru,bar,web,ham,ros,mas,bou,alo,nak,piq,rai,vet,bue,sut,fis]). gpx(china, [vet,web,but,bar,kov,ham,glo,bue,alo,rai,bou,hei,kub,fis,ros,piq,sut]). gpx(bahrain, [but,vet,tru,ham,bar,rai,glo,alo,ros,piq,web,kov,bou,mas,fis,sut,bue,kub,hei]). gpx(spain, [but,bar,web,vet,alo,mas,hei,ros,ham,glo,kub,piq,nak,fis]). gpx(monaco, [but,bar,rai,mas,web,ros,alo,bou,fis,glo,hei,ham,tru,sut,nak]). gpx(turkey, [but,web,vet,tru,ros,mas,kub,glo,rai,alo,hei,nak,ham,kov,bue,piq,sut,bou]). gpx(britain, [vet,web,bar,mas,ros,but,tru,rai,glo,fis,nak,piq,kub,alo,hei,ham,sut,bue]). 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_bottom_on_course_in(D,C) を作成せよ。D はドライバー名、C は国名である。たとえば、オーストラリアグランプリでは、ライコネン(rai)がビリだったので
ヒント:リストの最後の要素を表す規則を作れば良い。要素数が1つのリストの場合は、その要素が該当する。要素数が2つ以上のリストの場合、先頭を除くリストにおける最後の要素が該当する。
今回の練習で作成した知識の続きを作ろう。次のプログラムを作り、プログラムおよび実行結果にコメントを手書きで記載して提出せよ。
F1で1位と2位になった者が同一のチームである場合、ワンツーフィニッシュと言う。たとえば、オーストラリア、スペイン、モナコでは、チーム「ブラウンGP」のワンツーフィニッシュであった。また、中国、イギリスは「レッドブル」のワンツーフィニッシュであった。
そこで、チームTが国Cでワンツーフィニッシュとなったことを表す規則 one_two_finish(T,C) を作成せよ。
例えば、
?- one_two_finish(spain,'ブラウンGP').は Yes となる。
F1で1位から8位までの者は、入賞者といわれ、ポイントがもらえる。そこで、選手Pが国Cのグランプリで入賞したことを表す規則 praise_in(P,C) を作成せよ。P はニックネームとする。
同一のチームの2人が入賞したことをダブル入賞と言う。そこで、チームTが国Cのグランプリでダブル入賞したことを表す規則 double_praise_in(T,C) を作成せよ。
国Cのグランプリで選手Aと選手Bがともに完走し、かつ A が B の上位であったことを表す規則 gpx_greater_than_in( A, B, C ) を作成せよ。たとえば、ライコネン(rai)とマッサ(mas)が完走し、かつ、ライコネンがマッサより上位であったことは、バーレインとモナコの2回である。