/* Arranging flags puzzle in Picat. From Adrian Groza "Modelling Puzzles in First Order Logic" """ Puzzle 109. Arranging flags Komsomol youths have built a small hydroelectric powerhouse. Preparing for its open- ing, young communist boys and girls are decorating the powerhouse on all four sides with garlands, electric bulbs, and small flags. There are 12 flags. At first they arrange the flags 4 on a side, as shown, but then they see that the flags can be arranged 5 or even 6 on a side. How? (puzzle 19 from Kordemsky (1992)) (Fig. 11.1) """ It's not clear if the requirements are that 5 or 6 flags should be placed on both the upper/lower or left/right side. Here's the 4 + 4 + 4 + 4 version from Kordemsky f f f f ---------------------- | | f | | f | | f | | f | | ---------------------- f f f f In this model the values are coded as ul u ur --------- | | l | | r | | ---------- ll l lr Kordemsky's 4*4 version is thus encoded as 1 2 1 --------- | | 2 | | 2 | | ---------- 1 2 1 Koredemsky shows two solutions: 6 flags on each side 3 0 3 --------- | | 0 | | 0 | | ---------- 3 0 3 and 5 flags on each side 2 1 2 --------- | | 1 | | 1 | | ---------- 2 1 2 So it seems that the assumption is that there is a symmetry. There two solutions are found with Symmetry = full_symmetry in go/0. This program was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. /* With full symmetry (à la Kordemsky) there are 2 solutions, the one shown by Kordemsky: 3 0 3 --------- | | 0 | | 0 | | ---------- 3 0 3 and 2 1 2 --------- | | 1 | | 1 | | ---------- 2 1 2 */ go => N = 12, MinSides = 5, Symmetry = full_symmetry, arranging_flags(N,MinSides,Symmetry), fail, nl. /* With symmetry2 then there are a huge number of solutions, for example One side have 8 flags 4 0 4 --------- | | 0 | | 0 | | ---------- 0 0 4 One side have 7 flags 4 0 3 --------- | | 0 | | 0 | | ---------- 1 0 4 and - which is probably considered cheating - one with 12 sides 0 12 0 --------- | | 0 | | 0 | | ---------- 0 0 0 In total there are 4877 solutions with symmetry2 */ go2 => N = 12, MinSides = 5, Symmetry = symmetry2, arranging_flags(N,MinSides,Symmetry), fail, nl. /* With No symmetry breaking at all there are 50058 solutions, still requiring that at least one side should have >= 5 flags. */ go3 => N = 12, MinSides = 5, Symmetry = false, arranging_flags(N,MinSides,Symmetry), fail, nl. go4 => N = 12, MinSides = 11, Symmetry = symmetry2, arranging_flags(N,MinSides,Symmetry), fail, nl. arranging_flags(N,MinSides,Symmetry) => [Upper,Lower,Left,Right] :: 0..N, [UpperLeft,LowerLeft,UpperRight,LowerRight] :: 0..N, Upper + (UpperLeft + UpperRight) #>= MinSides #\/ Lower + (LowerLeft + LowerRight) #>= MinSides #\/ Left + (UpperLeft + LowerLeft ) #>= MinSides #\/ Right + (UpperRight + LowerRight) #>= MinSides, Ls = [Upper,Lower,Left,Right,UpperLeft,LowerLeft,UpperRight,LowerRight], N #= sum(Ls), % Symmetries % Full symmetry á la Kordemsky if Symmetry == full_symmetry then all_same([Upper,Left,Right,Lower]), all_same([UpperLeft,UpperRight,LowerLeft,LowerRight]) end, % Another symmetry breaking if Symmetry == symmetry2 then UpperLeft #= max([UpperLeft,UpperRight,LowerLeft,LowerRight]), Upper #= max([Upper,Left,Lower,Right]) end, solve(Ls), println(ls=Ls), printf("upper: %2d -> %2d\n",Upper,Upper+UpperLeft + UpperRight), printf("lower: %2d -> %2d\n",Lower,Lower+LowerLeft + LowerRight), printf("left : %2d -> %2d\n",Left,Left+UpperLeft + LowerLeft), printf("right: %2d -> %2d\n",Right,Right+UpperRight + LowerRight), println([ul=UpperLeft,ll=LowerLeft,ur=UpperRight,lr=LowerRight]), nl, printf(" %2d %2d %2d\n",UpperLeft,Upper,UpperRight), println(" ---------"), println(" | |"), printf(" %2d | | %2d\n",Left, Right), println(" | |"), println(" ----------"), printf(" %2d %2d %2d\n", LowerLeft,Lower,LowerRight), nl, fail, nl. all_same(X) => foreach(I in 2..X.len) X[I] #= X[I-1] end.