%
% Earthlings puzzle in MiniZinc.
%
% From Martin Chlond Integer Programming Puzzles
% http://www.chlond.demon.co.uk/puzzles/puzzles3.html, puzzle nr. 11
% Description : Earthlings
% Source : Poniachik, J. & L., (1998), Hard-to-solve Brainteasers, Sterling
%
% This model was inspired by the XPress Mosel model created by Martin Chlond.
% http://www.chlond.demon.co.uk/puzzles/sol3s11.html
%
% Model created by Hakan Kjellerstrand, hakank@bonetmail.com
% See also my MiniZinc page: http://www.hakank.org/minizinc
%
int: team = 3; % 1 = Zaire, 2 = Uruguay, 3 = Spain
int: place = 3; % 1st, 2nd or 3rd
int: ttype = 3; % 1 = truth-teller, 2 = alternator, 3 = liar
int: state = 3; % statements 1 = x(1,1)+x(2,2)+x(3,3)=3
% 2 = x(1,1)+x(3,2)+x(2,3)=3
% 3 = x(2,1)+x(3,2)+x(1,3)=3
set of 1..team: T = 1..team;
set of 1..place: P = 1..place;
set of 1..ttype: E = 1..ttype;
set of 1..state: S = 1..state;
% x(i,j) = 1 if team i in place j , 0 otherwise
array[T,P] of var 0..1: x; %
% y(k,l) = 1 if statement k made by type l
array[S, E] of var 0..1: y;
% d(k) = number of truths in statement k
array[S] of var 0..3: d;
solve satisfy;
constraint
% each place one team
forall(j in P) (
sum(i in T) (x[i,j]) = 1
)
/\
% each team one place
forall(i in T) (
sum(j in P) (x[i,j]) = 1
)
/\
% each type makes one statement
forall(k in E) (
sum(l in S) (y[k,l]) = 1
)
/\
% each statement made by one type
forall(l in S) (
sum(k in E) (y[k,l]) = 1
)
/\
% d[i] = number of truths in statement i
x[1,1]+x[2,2]+x[3,3] = d[1]
/\
x[1,1]+x[3,2]+x[2,3] = d[2]
/\
x[2,1]+x[3,2]+x[1,3] = d[3]
/\
forall(k in S) (
% if statement k made by truthteller (i.e. d[k]=3 ] then y[k,1] = 1, else 0
d[k] - 3*y[k,1] >= 0
)
/\
forall(k in S) (
d[k] - 3*y[k,1] <= 2
)
/\
% if statement k made by liar (i.e. d[k]=0 ] then y[k,3] = 1, else 0
forall(k in S) (
d[k] + 3*y[k,3] <= 3
)
/\
forall(k in S) (
d[k] + y[k,3] >= 1
)
/\
% assertion 1 and 3 either both true or both false for all statements
x[1,1]=x[3,3]
/\
x[1,1]=x[2,3]
/\
x[2,1]=x[1,3]
;
output [
if i = 1 /\ j = 1 then
"x:" else "" endif ++
if j = 1 then
"\n" else " " endif ++
show(x[i,j])
| i in T, j in T
] ++
[
if i = 1 /\ j = 1 then
"\ny:" else "" endif ++
if j = 1 then
"\n" else " " endif ++
show(y[i,j])
| i in S, j in E
] ++
[
if i = 1 then
"\nd:\n" else "\n" endif ++
show(d[i])
| i in S
];