2017年6月11日日曜日

Zebra Puzzle

たまたまTLに流れてきた
https://twitter.com/algoRafael0110/status/873469127364534272
に刺激されて、Zebra Puzzleを解くプログラムをPrologで書いてみました。

上記のツイートで言及されているのは、
http://qiita.com/ShunIchikawa/items/6449f492dc38a7201162
「Prolog実践入門 - AIに特化した老舗言語 - Qiita」
の簡易版と、英語版Wikipediaの解説
https://en.wikipedia.org/wiki/Zebra_Puzzle
「Zebra Puzzle - Wikipedia」

元のツイートで「is」述語を使っているのがパット見で気になって、「nth1があるよなぁ」と思いながらQiitaのページをちらっと見た後、自分で書いたら使う必要がなかった。。。

まぁこれで一応最低限は出来たと思います。

?- who(W, Z).

と問えばOK.
先のツイートで上手くいかなかったのを厳密に分析はしていませんが、is 述語はこの手の純粋なパズル系の問題では要注意だというのが私見です。

とりあえず。以下がコード。(SWI-Prologで確認。改行位置がきちゃないのはご勘弁を)

neighbour(X, Y, [X, Y| _]).
neighbour(X, Y, [Y, X| _]).
neighbour(X, Y, [_| R]) :- neighbour(X, Y, R).
right(X, Y, [Y, X| _]).
right(X, Y, [_| R]) :- right(X, Y, R).

who(Water, Zebra) :-
  Street = [H1, H2, H3, H4, H5],
  member(house(englishman, red, _, _, _), Street),
  member(house(spaniard, _, dog, _, _), Street),
  member(house(_, green, _, coffee, _), Street),
  member(house(ukrainian, _, _, tea, _), Street),
  right(house(_, green, _, _, _), house(_, ivory, _, _, _), Street),
  member(house(_, _, snails, _, old_gold), Street),
  member(house(_, yellow, _, _, kools), Street),
  house(_, _, _, milk, _) = H3,
  house(norwegian, _, _, _, _) = H1,
  neighbour(house(_, _, _, _, chesterfields), house(_, _, fox, _, _), Street),
  neighbour(house(_, _, _, _, kools), house(_, _, horse, _, _), Street),
  member(house(_, _, _, orange_juice, lucky_strike), Street),
  member(house(japanese, _, _, _, parliaments), Street),
  neighbour(house(norwegian, _, _, _, _), house(_, blue, _, _, _), Street),
  member(house(Water, _, _, water, _), Street),
  member(house(Zebra, _, zebra, _, _), Street).