状況設定
DCG と良い子悪い子普通の子 よりもう少し複雑な状況を考えます。
ある学校には、良い子、悪い子、普通の子の三種類の生徒がいます。
- 良い子はいつも正直です。
- 悪い子はいつも嘘をつきます。
- 普通の子は正直なときもあれば、嘘をつくときもあります。
テストの成績はだいたい見当がつくとおり、
- 良い子はいつもいい成績を、
- 悪い子には及第点ぎりぎりの成績を、
- 普通の子は良くも悪くもないそこそこの成績を、
それぞれとります。なので、いつでも成績順は
良い子の成績 > 普通の子の成績 > 悪い子の成績
になっています。
さて、良い子、悪い子、普通の子の三人が集まって話をしているのを小耳にはさみました。
- A は『B の成績は C の成績より高い』と言っていました。
- B は『C の成績は A の成績より高い』と言っていました。
- C も『... の成績は ... の成績より高い』と呟いていましたが、よく聞こえませんでした。
さて、C はなんと言っていたでしょうか。
解いてみる
三種類の生徒の成績の良し悪しを比較する演算子として >
を使ってもよさそうです。
しかし、やってみると DCG で具合が悪いので、代わりに >>
を演算子として定義しておきます:
:- op(700, xfx, '>>').
これを使って、状況を以下のように書き表してみます:
状況 -->
% 良い子、悪い子、普通の子の三人がいる。
% A, B, C のどれがどの子かは不明。
{ permutation([良い子, 悪い子, 普通の子], [_属性A, _属性B, _属性C]),
A = 生徒('A', _属性A),
B = 生徒('B', _属性B),
C = 生徒('C', _属性C) },
% 言及: A が『B の成績は C より高い』と言った
言及する(A, 成績(B) >> 成績(C)),
% 言及: B が『C の成績は A より高い』と言った
言及する(B, 成績(C) >> 成績(A)),
% 言及: C が、A, B の成績についてなにかを言った
{ permutation([A, B], [AorB1, AorB2]) },
言及する(C, 成績(AorB1) >> 成績(AorB2)).
それぞれの言及について、内容を検証しつつ文章として組み立てる処理を書くと、こんな感じです:
言及する(_生徒, _文)
--> { 検証する(_生徒, _文, _真偽),
_生徒 = 生徒(_名前, _属性) },
[_名前, '(', _属性, ')', が, '『'], _文, ['』(', _真偽, ')', と言った, '。\n'].
成績(X) >> 成績(Y)
-->
{ X = 生徒(_名前X, _属性X),
Y = 生徒(_名前Y, _属性Y) },
[_名前X, '(', _属性X, ')の成績は', _名前Y, '(', _属性Y, ')の成績より高い'].
それぞれが成績順について言及した内容を検証する手続きは、以下のように書けます:
検証する(生徒(_, 良い子), _文章, 真) :- call(_文章).
検証する(生徒(_, 悪い子), _文章, 偽) :- \+ call(_文章).
検証する(生徒(_, 普通の子), _文章, 真) :- call(_文章).
検証する(生徒(_, 普通の子), _文章, 偽) :- \+ call(_文章).
% 成績の良し悪しは属性から自動的に決まる
成績(生徒(_, 良い子)) >> 成績(生徒(_, 普通の子)).
成績(生徒(_, 普通の子)) >> 成績(生徒(_, 悪い子)).
成績(生徒(_, 良い子)) >> 成績(生徒(_, 悪い子)).
状況を表す文全てを出力する手続きを書くと:
解を得る(_一つの文) :-
phrase(状況, _状況を表す文章),
atomic_list_concat(_状況を表す文章, _一つの文).
解を表示する :-
解を得る(_一つの文),
write('==== 解 ====\n'),
write(_一つの文),
fail. % 失敗駆動ループ
solve :- 解を表示する.
実行結果
実行すると、こんな解が得られました。
?- solve.
==== 解 ====
A(良い子)が『B(普通の子)の成績はC(悪い子)の成績より高い』(真)と言った。
B(普通の子)が『C(悪い子)の成績はA(良い子)の成績より高い』(偽)と言った。
C(悪い子)が『B(普通の子)の成績はA(良い子)の成績より高い』(偽)と言った。
==== 解 ====
A(悪い子)が『B(普通の子)の成績はC(良い子)の成績より高い』(偽)と言った。
B(普通の子)が『C(良い子)の成績はA(悪い子)の成績より高い』(真)と言った。
C(良い子)が『B(普通の子)の成績はA(悪い子)の成績より高い』(真)と言った。
false.
なので、C は『B の成績は A の成績より高い』と言っていた、というのが問題の答えです。