/* The courageous garrison in Picat. From Adrian Groza "Modelling Puzzles in First Order Logic" """ Puzzle 117. The courageous garrison A courageous garrison was defending a snow fort. The commander arranged his forces as shown in the square frame (the inner square showing garrison’s total strength of 40 boys): 11 boys defending each side of the fort. The garrison "lost" 4 boys dur- ing each of the first, second, third, and fourth assaults, and 2 during the fifth and last. But after each charge 11 boys defended each side of the snow fort. How? (puzzle 101 from Kordemsky (1992)) """ Initial configuration 1 9 1 --------- | | 9 | 40 | 9 | | ---------- 1 9 1 For 40, 36, 32, 28, and 24 there are (unique) solutions with total symmetry, but not for 22 (which has to be solved without symmetries). Here are the first solutions for each number, with symmetry if possible. total = 40 1 9 1 --------- | | 9 | | 9 | | ---------- 1 9 1 total = 36 2 7 2 --------- | | 7 | | 7 | | ---------- 2 7 2 total = 32 3 5 3 --------- | | 5 | | 5 | | ---------- 3 5 3 total = 28 4 3 4 --------- | | 3 | | 3 | | ---------- 4 3 4 total = 24 5 1 5 --------- | | 1 | | 1 | | ---------- 5 1 5 total = 22 0 0 11 --------- | | 0 | | 0 | | ---------- 11 0 0 Here is another solution for 22: 5 0 6 --------- | | 0 | | 0 | | ---------- 6 0 5 Some similar puzzles: - a_mysterious_box.pi - arranging_flags.pi This program was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go => NumSide = 11, foreach(Total in [40,36,32,28,24,22]) Symmetry = cond(Total > 22, true, false), println(total=Total), the_courageous_garrison(Total,NumSide,Symmetry) end, nl. /* Number of solutions, all with 11 on each side. [total = 40,symmetry = true,count = 1] [total = 36,symmetry = true,count = 1] [total = 32,symmetry = true,count = 1] [total = 28,symmetry = true,count = 1] [total = 24,symmetry = true,count = 1] [total = 40,symmetry = false,count = 35] [total = 36,symmetry = false,count = 165] [total = 32,symmetry = false,count = 407] [total = 28,symmetry = false,count = 329] [total = 24,symmetry = false,count = 91] [total = 22,symmetry = false,count = 12] Checking totals of 1..100 show some other working instances, for example 44 with symmetries and some with odd totals. [total = 24,symmetry = true,count = 1] [total = 28,symmetry = true,count = 1] [total = 32,symmetry = true,count = 1] [total = 36,symmetry = true,count = 1] [total = 40,symmetry = true,count = 1] [total = 44,symmetry = true,count = 1] [total = 22,symmetry = false,count = 12] [total = 23,symmetry = false,count = 44] [total = 24,symmetry = false,count = 91] [total = 25,symmetry = false,count = 148] [total = 26,symmetry = false,count = 210] [total = 27,symmetry = false,count = 272] [total = 28,symmetry = false,count = 329] [total = 29,symmetry = false,count = 376] [total = 30,symmetry = false,count = 408] [total = 31,symmetry = false,count = 420] [total = 32,symmetry = false,count = 407] [total = 33,symmetry = false,count = 364] [total = 34,symmetry = false,count = 286] [total = 35,symmetry = false,count = 220] [total = 36,symmetry = false,count = 165] [total = 37,symmetry = false,count = 120] [total = 38,symmetry = false,count = 84] [total = 39,symmetry = false,count = 56] [total = 40,symmetry = false,count = 35] [total = 41,symmetry = false,count = 20] [total = 42,symmetry = false,count = 10] [total = 43,symmetry = false,count = 4] [total = 44,symmetry = false,count = 1] */ go2 => NumSide = 11, member(Symmetry, [true,false]), nl, member(Total,[40,36,32,28,24,22]), % member(Total,1..100), Count = count_all(the_courageous_garrison(Total,NumSide,Symmetry,false)), if Count > 0 then println([total=Total,symmetry=Symmetry,count=Count]) end, fail, nl. the_courageous_garrison(Total,NumSides,Symmetry) => the_courageous_garrison(Total,NumSides,Symmetry,true). the_courageous_garrison(Total,NumSides,Symmetry,Print) => Max = 11, X = [Upper,Left,Right,Lower, UL,UR,LL,LR], X :: 0..Max, Upper + (UL + UR) #= NumSides, Lower + (LL + LR) #= NumSides, Left + (UL + LL) #= NumSides, Right + (UR + LR) #= NumSides, Total #= sum(X), % "Total" symmetry if Symmetry then all_same([Upper,Left,Right,Lower]), all_same([UL,UR,LL,LR]) end, solve(X), if Print then println(x=X=Total), println(total=Total), printf("upper: %2d -> %2d\n",Upper,Upper+UL+UR), printf("lower: %2d -> %2d\n",Lower,Lower+LL+LR), printf("left : %2d -> %2d\n",Left,Left+UL+LL), printf("right: %2d -> %2d\n",Right,Right+UR+LR), % println([ul=UL,ll=LL,ur=UR,lr=LR]), nl, nl, printf(" %2d %2d %2d\n",UL,Upper,UR), println(" ---------"), println(" | |"), printf(" %2d | | %2d\n",Left, Right), println(" | |"), println(" ----------"), printf(" %2d %2d %2d\n", LL,Lower,LR), nl end. all_same(X) => foreach(I in 2..X.len) X[I] #= X[I-1] end.