LoginSignup
0
0

More than 1 year has passed since last update.

DCG と良い子悪い子普通の子(演算子を定義してみる編)

Posted at

状況設定

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 の成績より高い』と言っていた、というのが問題の答えです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0