/* Four alike pals problem in Picat. From the Swedish blog post "Fyra lika kompisar" (Four alike pals): http://mattebloggen.com/2012/12/fyra-lika-kompisar/ (translated by me) """ Four friends are alike in many ways: for all pairs, the pair has the same first name or the same name or the same birth date. However, no three of the friends has the same first name, no three have the same last name, nor there are there three with the same birth date. Can this kind of four friends exists? """ Solution: If we allow for 1..n first names/last names/birthdays, there are 10368 different solutions. The smallest number of first names/last names/birthdays is 2 (the z value which is then minimized). first_name: [1, 2, 2, 1] last_name : [2, 2, 1, 1] birthday : [2, 1, 2, 1] z : 2 There are 48 different solutions with 2 different first names/last names/birthdays. With the symmetry breaking that the first person is called 1 1 and has birthday 1 then there are 6 optimal solutions. This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go ?=> N = 4, Cover = 1..N, LimitLow = [0 : _ in 1..N], LimitHigh = [2 : _ in 1..N], % decision variables FirstName = new_list(N), FirstName :: 1..N, LastName = new_list(N), LastName :: 1..N, Birthday = new_list(N), Birthday :: 1..N, Z #= max($(FirstName ++ LastName ++ Birthday).vars), Z #= 2, % same pair foreach(I in 1..N, J in I+1..N) FirstName[I] #= FirstName[J] #\/ LastName[I] #= LastName[J] #\/ Birthday[I] #= Birthday[J] end, global_cardinality_low_up(FirstName, Cover, LimitLow, LimitHigh), global_cardinality_low_up(LastName, Cover, LimitLow, LimitHigh), global_cardinality_low_up(Birthday, Cover, LimitLow, LimitHigh), % Symmetry breaking FirstName[1] #= 1, LastName[1] #= 1, Birthday[1] #= 1, Vars = FirstName ++ LastName ++ Birthday, % solve($[min(Z)],Vars), solve($[],Vars), println(firstName=FirstName), println('lastName '=LastName), println('birthday '=Birthday), println(z=Z), nl, fail, nl. go => true. global_cardinality_low_up(V,C,Low,Up) => T = new_list(C.len), foreach(I in 1..C.len) T[I] :: Low[I]..Up[I] end, Gcc = $[C[I]-T[I] : I in 1..C.len], global_cardinality(V,Gcc).