/*
7.A farmer leaves 45 casks of wine, of which 9 each are full,
three-quarters full, half full, one quarter full and empty. His five
nephews want to divide the wine and the casks without changing wine
from cask to cask in such a way that each receives the same amount of
wine and the same number of casks, and further so that each receives
at least one of each kind of cask, and no two of them receive the same
number of every kind of cask. (Kraitchik)
*/
:- lib(ic).
:- lib(ic_global).
:- lib(matrix_util).
solve(Nephews) :-
% For each nephew we have a list of 5 variables indicating
% how many casks of each capacity he gets
matrix(5, 5, Nephews, Caps),
Capacities = [0,1,2,3,4], % in quarters
( foreach(Nephew, Nephews), param(Capacities) do
sum(Nephew) #= 9, % Each nephew receives 9 casks
Nephew :: 1..9, % and between 1 and 9 of each type
Nephew*Capacities #= 18 % Each nephew receives 18 units of wine
),
( foreach(Cap, Caps) do
sum(Cap) #= 9 % There are 9 casks of each type
),
strictly_ascending(Nephews), % No permutations or duplicates
( foreach(Cap, Caps) do % search
( foreach(Cask, Cap) do
indomain(Cask)
)
),
( foreach(Nephew, Nephews) do % print solution
writeln(Nephew)
).
% Auxiliary constraint definition: this imposes a strict order on
% the Nephew-lists to implement the non-duplicate condition.
% It also removes symmetries as a useful side effect.
strictly_ascending(Vectors) :-
( for(I,0,4), foreach(W, Weights) do
W is 9^I
),
( foreach(Vector, Vectors), foreach(VectorWeight, VectorWeights), param(Weights) do
Vector*Weights #= VectorWeight
),
ordered(<, VectorWeights).