/* Farm puzzle in Picat. From http://www.cs.st-andrews.ac.uk/~andrea/tailor/examples.html """ A farmer has 7 animals on his farm: pigs and hens. They all together have 22 legs. How many pigs (4 legs) and how many hens (2 legs) does the farmer have? """ 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 ?=> NumberOfLegs = 22, Feet = [2,4], % number of feet X = new_list(7), % the seven animals X :: Feet, sum(X) #= NumberOfLegs, increasing(X), % symmetry breaking (to make the solution unique) % Count of the number of each type of feet Gcc = $[I-C : I in 0..4], global_cardinality(X,Gcc), Vars = X ++ Gcc, solve(Vars), println(x=X), println(gcc=Gcc), C = new_map([L=N : $L-N in Gcc]), println(c=C), println('numberOfHens (2 legs)'=C.get(2)), println('numberOfPigs (4 legs)'=C.get(4)), nl, fail, nl. go => true. % % Different use of global cardinality % go2 ?=> NumberOfLegs = 22, Feet = [2,4], % number of feet X = new_list(7), % the seven animals X :: Feet, sum(X) #= NumberOfLegs, increasing(X), % symmetry breaking (to make the solution unique) % Count of the number of each type of feet, % i.e number of 1 legs, 2 legsm, 3 legs, and 4 legs Gcc = new_list(4), Gcc :: 0..22, global_cardinality2(X,Gcc), Vars = X ++ Gcc, solve(Vars), println(x=X), println(gcc=Gcc), nl, fail, nl. go2 => true. % % A simpler approach a. % go3 ?=> Pigs #> 0, Hens #> 0, Pigs*4 + Hens*2 #= 22, Pigs + Hens #= 7, solve([Pigs,Hens]), println(pigs=Pigs), println(hens=Hens), fail, nl. go3 => true. % % A simpler approach b. % This is better since we have explicit % domains of Pigs and Hens. % go4 ?=> TotalNumLegs = 22, Animals = [Pigs, Hens], Animals :: 0..TotalNumLegs, Pigs*4 + Hens*2 #= TotalNumLegs, Pigs + Hens #= 7, solve(Animals), println(pigs=Pigs), println(hens=Hens), fail, nl. go4 => true. % % Both A and Gcc are lists. % % This version is bidirectional but limited: % % The list A can contain only values 1..Max (i.e. the length of Gcc). % This means that the caller must know the max values of A. % Or rather: if A contains another values they will not be counted. % global_cardinality2(A, Gcc) => Len = length(A), Max = length(Gcc), Gcc :: 0..Len, foreach(I in 1..Max) count(I,A,#=,Gcc[I]) end.