/*
Bertrand Russell puzzle in Picat.
From http://stackoverflow.com/questions/26809266/bertrand-russell-puzzle
"""
As a simple exercise in abstraction suppose that four meaningless
symbols a, b, c, and d correspond in one order or another to the
equally meaningless symbols w, x, y, and z, and suppose further that
If a is not x, then c is not y.
If b is either y or z, then a is x.
If c is not w, then b is z.
If d is y, then b is not x.
If d is not x, then b is x.
In what order do the two sets of symbols correspond?
"""
(The problem is also in "101 puzzles in Thought and Logic", page 58)
Here we show three different version:
- "pure" CP
- logic programming version of the CP version
- "pure" LP
Solution:
a<=>y
b<=>x
c<=>w
d<=>z
This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com
See also my Picat page: http://www.hakank.org/picat/
*/
% import util.
import cp.
main => go.
go =>
All = findall([abcd=ABCD,wxyz=WXYZ,Connection],puzzle_cp(ABCD,WXYZ,Connection)),
foreach([ABCD,WXYZ,Connection] in All)
println(abcd=ABCD),
println(wxyz=WXYZ),
foreach(C in Connection) println(C) end
end,
nl.
go2 =>
All = findall([abcd=ABCD,wxyz=WXYZ,Connection],puzzle_lp(ABCD,WXYZ,Connection)),
foreach([ABCD,WXYZ,Connection] in All)
println(abcd=ABCD),
println(wxyz=WXYZ),
foreach(C in Connection) println(C) end
end,
nl.
go3 =>
All = findall(L,puzzle_lp2(L)),
foreach(L in All)
foreach([AA,WW] in L)
printf("%w<=>%w\n", AA,WW)
end
end,
nl.
%
% CP approach
%
puzzle_cp(ABCD,WXYZ, Connection) =>
N = 4,
% Symmetry breaking: A..D are ordered
A = 1,
B = 2,
C = 3,
D = 4,
ABCD = [A,B,C,D],
ABCD_S = "abcd",
W :: 1..N,
X :: 1..N,
Y :: 1..N,
Z :: 1..N,
WXYZ = [W,X,Y,Z],
WXYZ_S = "wxyz",
all_different(WXYZ),
% If a is not x, then c is not y.
(A #!= X #=> C #!= Y),
% If b is either y or z, then a is x.
( ( (B #= Y) #\/ (B #= Z)) #=> A #= X),
% If c is not w, then b is z.
( C #!= W #=> B #= Z),
% If d is y, then b is not x.
( D #= Y #=> B #!= X),
% If d is not x, then b is x.
( D #!= X #=> B #= X),
solve(WXYZ),
Connection = [ABCD_S[I].to_string() ++ "<=>" ++ WXYZ_S[J].to_string() : I in 1..N, J in 1..N, WXYZ[J] == I].
%
% Same approach as CP but in pure LP
%
puzzle_lp(ABCD,WXYZ,Connection) =>
N = 4,
A = 1,
B = 2,
C = 3,
D = 4,
ABCD = [A,B,C,D],
ABCD_S = "abcd",
member(W,1..4),
member(X,1..4),
member(Y,1..4),
member(Z,1..4),
WXYZ = [W,X,Y,Z],
WXYZ_S = "wxyz",
% If a is not x, then c is not y.
(A != X -> C != Y ; true),
% If b is either y or z, then a is x.
( ( (B = Y) ; (B = Z)) -> A = X ; true),
% If c is not w, then b is z.
( C != W -> B = Z ; true),
% If d is y, then b is not x.
( D = Y -> B != X ; true),
% If d is not x, then b is x.
( D != X -> B = X ; true),
% foreach(I in 1..N, J in 1..N, I < J)
% ABCD[I] != ABCD[J],
% WXYZ[I] != WXYZ[J]
% end,
all_different(ABCD),
all_different(WXYZ),
Connection = [ABCD_S[I].to_string() ++ "<=>" ++ WXYZ_S[J].to_string() : I in 1..N, J in 1..N, WXYZ[J] == I].
%
% A "purer" LP approach
%
puzzle_lp2(L) =>
L=[[a,C1],[b,C2],[c,C3],[d,C4]],
member(C1,[w,x,y,z]),
member(C2,[w,x,y,z]),
member(C3,[w,x,y,z]),
member(C4,[w,x,y,z]),
% CC = [C1,C2,C3,C4],
% foreach(I in 1..4, J in 1..4, I < J)
% CC[I] != CC[J]
% end,
all_different([C1,C2,C3,C4]),
% If a is not x, then c is not y.
(C1 = x -> C3 != y ; true),
% If b is either y or z, then a is x.
( (C2 = y ; C2 = z) -> C1 = x ; true),
% If c is not w, then b is z.
( C3 != w -> C2 = z ; true ),
% If d is y, then b is not x.
( C4 = y -> C2 != x ; true),
% If d is not x, then b is x.
( C4 != x -> C2 = x ; true).