/* Spinning disks problem in Picat. From Skeptic's Play "The Spinning Disks" http://skepticsplay.blogspot.com/2010/03/spinning-disks.html """ I have this disk. It's shaped like a CD, and divided into twelve sectors. Some of those sectors are opaque, and some are transparent. But the opaque and transparent sectors are not arranged in the particular order shown above. Actually, I have two disks like this. They're completely identical to each other. I place the two disks on top of each other. You can see through some sectors and not through others. And then I begin to spin the top disk. Every time it rotates one twelfth of a full circle, the number of transparent sectors changes. It forms a sequence of numbers. Here's part of the sequence: ..., 2, 3, 4, 4, 0, 4, ... Which sectors of the disk are transparent, and which are not? """ The trick is to reverse the disk, i.e. turn it around disk1 has the following four solutions (shift symmetries) disk1: 1 1 0 0 1 1 0 0 1 0 1 0 disk1: 1 1 0 1 0 1 0 0 1 1 0 0 disk1: 0 0 1 1 0 0 1 1 0 1 0 1 disk1: 0 0 1 0 1 0 1 1 0 0 1 1 The complete transparant sequence is 2 3 4 4 0 4 4 3 2 3 4 3 Here is one solution with the rotated disk2: Disk1: [0,0,1,0,1,0,1,1,0,0,1,1] Disk2: {1,1,0,0,1,1,0,1,0,1,0,0} {1,0,0,1,1,0,1,0,1,0,0,1} {0,0,1,1,0,1,0,1,0,0,1,1} {0,1,1,0,1,0,1,0,0,1,1,0} {1,1,0,1,0,1,0,0,1,1,0,0} {1,0,1,0,1,0,0,1,1,0,0,1} {0,1,0,1,0,0,1,1,0,0,1,1} {1,0,1,0,0,1,1,0,0,1,1,0} {0,1,0,0,1,1,0,0,1,1,0,1} {1,0,0,1,1,0,0,1,1,0,1,0} {0,0,1,1,0,0,1,1,0,1,0,1} {0,1,1,0,0,1,1,0,1,0,1,0} sums = {2,3,4,4,0,4,4,3,2,3,4,3} 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 => % Number of sectors in each disk N = 12, % Disk1 % 1: transparent, 0: not transparent Disk1 = new_list(N), Disk1 :: 0..1, % Number of the known sum sequence M = 12, % the sum sequence Sums = new_array(M), M :: 0..N, % disk2 with all the rotations % Note: first entry is disk1 turned around (reversed) Disk2 = new_array(M,N), Disk2 :: 0..1, % Reverse the disk2 (i.e. turn it around) reverse(Disk1, [Disk2[1,I] : I in 1..N]), foreach(Rot in 1..M) if Rot > 1 then foreach(I in 1..N) Disk2[Rot,I] #= Disk2[Rot-1, 1+ I mod N] end end, Sums[Rot] #= sum([Disk1[I] + Disk2[Rot,I] #= 2 : I in 1..N]) end, % The given sum sequence Sums = {2,3,4,4,0,4,_,_,_,_,_,_}, % Symmetry breaking % But there still is one shift symmetric solution Disk1[1] #= 0, Vars = Disk1 ++ Disk2, solve(Vars), println("Disk1:"), println(Disk1), println("Disk2:"), foreach(Row in Disk2) println(Row) end, println(sums=Sums), nl, fail, nl. % % reverse an array % reverse(X, Rev) => Len = X.len, foreach(I in 1..Len) Rev[I] #= X[Len-I+1] end.