うそつき娘問題を制約プログラミングで解く

ネットで以下の問題を見つけたのでSWI-PrologのCLPFDライブラリで解いてみた

問題:水泳大会

水泳大会で、この4人が1位から4位を獲得しました(同順位はありません)。

スタート前の予想は下のとおりで、3人が当たり、1人が外れました。

誰が何位だったのでしょう?

ことり「私は1位」
なる 「私はすずより上位」
すず 「私は1位か2位」
あゆ 「私は1位か2位」

プログラム:

:-use_module(library(clpfd)).

solve_girl_order:-
GirlOrderLst = [KotoriOrder,NaruOrder,SuzuOrder,AyuOrder],
GirlOrderLst ins 1..4,
all_different(GirlOrderLst),
HatugenFlgLst = [KotoriHatugenFlg,NaruHatugenFlg,SuzuHatugenFlg,AyuHatugenFlg],
HatugenFlgLst ins 0..1,
appear_times(HatugenFlgLst,0,1),

KotoriHatugenFlg #<==> (KotoriOrder #= 1),
NaruHatugenFlg #<==> (NaruOrder #< SuzuOrder),
SuzuHatugenFlg #<==> (SuzuOrder #= 1 #\/ SuzuOrder #= 2),
AyuHatugenFlg #<==> (AyuOrder #= 1 #\/ AyuOrder #= 2),

label(GirlOrderLst),
label(HatugenFlgLst),
write(GirlOrderLst),
write(HatugenFlgLst).

% appear_times( Lst, Num, Times)
% [Num] appears [Times] times in [Lst]
appear_times(Lst,Num,Times):-
maplist(eq_b(Num),Lst,Bs),
sum(Bs,#=,Times).
eq_b(X,Y,B):-(X#=Y) #<==>B.

実行結果:

[1] 4 ?- girl_order.
[1,3,4,2][1,1,0,1]
true ;
false.

実行結果は
[ことり順位,なる順位,すず順位,あゆ順位]
[ことり発言,なる発言,すず発言,あゆ発言 (1:真実 0:嘘)]

プログラム作成に10分くらいかかった。

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です