Erlangとジャンケン

SequenceableCollection >> #after: を使ってジャンケンの勝敗判定経由でPrologの話をしよう - CROSS2012・言語CROSSにあるジャンケン判定をErlangで真似てみました。

-module(janken).
-compile(export_all).

win(goo, choki) -> true;
win(choki, par) -> true;
win(par, goo) ->  true;
win(_, _) -> false.

judge(P, P) -> even;
judge(P1, P2) ->
    J1 = win(P1, P2),
    J2 = win(P2, P1),
    if
        J1 -> winner_is_p1;
        J2 -> winner_is_p2;
    end.

実際に動かしてみます…

3> janken:judge(goo, choki).
winner_is_p1
4> janken:judge(goo, goo).
even
5> janken:judge(goo, par).
winner_is_p2

よいようです。しかし単にパターンマッチングをしているだけなので面白くないですね…。

オリジナルのPrologソースを少しいじってみました。

win(goo, choki).
win(choki, par).
win(par, goo).

even(goo, goo).
even(choki, choki).
even(par, par).

judge(P1, P2, winner_is_p1) :- win(P1, P2).
judge(P1, P2, winner_is_p2) :- win(P2, P1).
judge(P1, P2, even) :- even(P1, P2).

GNU Prologで実行してみます。

zinnia@tulip:/tmp[5]% gprolog 
GNU Prolog 1.3.0
By Daniel Diaz
Copyright (C) 1999-2007 Daniel Diaz
| ?- ['janken.pl'].
compiling /tmp/janken.pl for byte code...
/tmp/janken.pl compiled, 11 lines read - 1144 bytes written, 18 ms

(1 ms) yes
| ?- judge(goo, par, Result).

Result = winner_is_p2 ? a           % グー対パーではパーが勝つ。

no
| ?- judge(par, par, Result).

Result = even                       % パー対パーは引き分け。

yes
| ?- judge(P1, par, winner_is_p1).  % 相手(P2)がパーを出したときに勝てる手は?

P1 = choki ? a                      % チョキ

no
| ?- judge(P1, P2, winner_is_p2).   % 相手(P2)が勝つ手をすべて挙げる。

P1 = choki
P2 = goo ? a

P1 = par
P2 = choki

P1 = goo
P2 = par

no
| ?- judge(P1, P2, Result).         % すべての手と勝敗を挙げる。

P1 = goo
P2 = choki
Result = winner_is_p1 ? a

P1 = choki
P2 = par
Result = winner_is_p1

P1 = par
P2 = goo
Result = winner_is_p1

P1 = choki
P2 = goo
Result = winner_is_p2

P1 = par
P2 = choki
Result = winner_is_p2

P1 = goo
P2 = par
Result = winner_is_p2

P1 = goo
P2 = goo
Result = even

P1 = choki
P2 = choki
Result = even

P1 = par
P2 = par
Result = even

yes

こういう柔軟な問い合わせができるのはやっぱりPrologならではですね。