/*
Monks and doors problem in SICStus Prolog.
From http://user.it.uu.se/~rolandb/LP/gammal/960615_facit.ps
"""
There is a room with four doors and eight monks. One or more of
the doors may be exit. Each monk is either telling a lie or the truth.
The monks make the following statements:
Monk 1: Door A is the exit.
Monk 2: At least one of the doors B and C is the exit.
Monk 3: Monk 1 and Monk 2 are telling the truth.
Monk 4: Doors A and B are both exits.
Monk 5: Doors A and B are both exits.
Monk 6: Either Monk 4 or Monk 5 is telling the truth.
Monk 7: If Monk 3 is telling the truth, so is Monk 6.
Monk 8: If Monk 7 and Monk 8 are telling the truth, so is Monk 1.
Which door is an exit no matter who is a liar and who is telling the
truth.
"""
Answer: Door A is an exit.
And monks 1, 7, and 8 are telling the truth.
Also, see the following models
* MiniZinc: http://www.hakank.org/minizinc/monks_and_doors.mzn
* ECLiPSe : http://www.hakank.org/eclipse/monks_and_doors.ecl
Model created by Hakan Kjellerstrand, hakank@bonetmail.com
See also my SICStus Prolog page: http://www.hakank.org/sicstus/
*/
:-use_module(library(clpfd)).
:-use_module(library(lists)).
go :-
Doors = [A,B,C,D],
domain(Doors,0,1),
Monks = [M1,M2,M3,M4,M5,M6,M7,M8],
domain(Monks,0,1),
% Monk 1: Door A is the exit.
M1 #= A,
% Monk 2: At least one of the doors B and C is the exit.
M2 #= 1 #<=> (B + C #>= 1),
% Monk 3: Monk 1 and Monk 2 are telling the truth.
M3 #= 1 #<=> (M1 #/\ M2),
% Monk 4: Doors A and B are both exits.
M4 #= 1 #<=> (A #/\ B) ,
% Monk 5: Doors A and C are both exits.
M5 #= 1 #<=> (A #/\ C),
% Monk 6: Either Monk 4 or Monk 5 is telling the truth.
M6 #= 1 #<=> (M4 #\/ M5),
% Monk 7: If Monk 3 is telling the truth, so is Monk 6.
M7 #= 1 #<=> (M3 #=> M6),
% Monk 8: If Monk 7 and Monk 8 are telling the truth, so is Monk 1.
M8 #= 1 #<=> ((M7 #/\ M8) #=> (M1)),
% Exactly one door is an exit.
(A + B + C + D) #= 1,
append(Doors, Monks, FD),
labeling([], FD),
write(exit_doors:Doors),nl,
write(truth_telling_monks:Monks),nl.