/* A mysterious box in Picat. From Adrian Groza "Modelling Puzzles in First Order Logic" """ Puzzle 116. A mysterious box Misha brought a pretty little box for his sister Irochka from his Crimean summer camp. She was not of school age yet, but could count to 10. She liked the box because she could count 10 sea shells along each side, as shown. One day, Irochka’s mother, while cleaning the box, accidentally broke 4 shells. "No great trouble", Misha said. He unstuck some of the remaining 32 shells, then pasted them on so that there were again 10 shells along each side of the cover, and the box was as symmetrical as before. How did he do it? A few days later, when the box fell on the floor and 6 more shells were crushed, Misha again redistributed the shells—though not quite so symmetrically—so Irochka could count 10 on each side. Can you find one of the many solutions? (puzzle 100 from Kordemsky (1992)) (Fig. 11.11) """ Initial: 1 8 1 --------- | | 8 | | 8 | | ---------- 1 8 1 For Total = 32 and "total" symmetry, there's a single solution: total = 32 upper: 6 -> 10 lower: 6 -> 10 left : 6 -> 10 right: 6 -> 10 2 6 2 --------- | | 6 | | 6 | | ---------- 2 6 2 For Total = 26 and no symmetry there are 110 solutions, for example total = 26 upper: 1 -> 10 lower: 5 -> 10 left : 1 -> 10 right: 5 -> 10 5 1 4 --------- | | 1 | | 5 | | ---------- 4 5 1 total = 26 upper: 5 -> 10 lower: 1 -> 10 left : 5 -> 10 right: 1 -> 10 3 5 2 --------- | | 5 | | 1 | | ---------- 2 1 7 See go2/0 for the number of solutions for some other problem instances. Cf arranging_flags.pi (also from Groza) 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 => Problems = [[10,32,true], [10,26,false]], foreach([NumSides,Total,Symmetry] in Problems) println([numSides=NumSides,total=Total,symmetry=Symmetry]), _ = findall(_,a_mysterious_box(Total,NumSides,Symmetry)) end, % fail, nl. /* Let's find more solutions with 10 on each side but different total (and symmetry) [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 = 22,symmetry = false,count = 8] [total = 23,symmetry = false,count = 28] [total = 24,symmetry = false,count = 55] [total = 25,symmetry = false,count = 84] [total = 26,symmetry = false,count = 110] [total = 27,symmetry = false,count = 128] [total = 28,symmetry = false,count = 133] [total = 29,symmetry = false,count = 120] [total = 30,symmetry = false,count = 84] [total = 31,symmetry = false,count = 56] [total = 32,symmetry = false,count = 35] [total = 33,symmetry = false,count = 20] [total = 34,symmetry = false,count = 10] [total = 35,symmetry = false,count = 4] [total = 36,symmetry = false,count = 1] */ go2 => NumSides = 10, Print = false, member(Symmetry,[true,false]), nl, member(Total, 1..50), Count = count_all(a_mysterious_box(Total,NumSides,Symmetry,Print)), if Count > 0 then println([total=Total,symmetry=Symmetry, count=Count]) end, fail, nl. a_mysterious_box(Total,NumSides,Symmetry) => a_mysterious_box(Total,NumSides,Symmetry,true). a_mysterious_box(Total,NumSides,Symmetry,Print) => Max = 10, X = [Upper,Left,Right,Lower, UL,UR,LL,LR], X :: 1..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), 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.