/* Invisible dice in Picat. From https://brainstellar.com/puzzles/probability/24 """ Invisible Dice I bought two fair six-sided dice. Keeping the first one untouched, I modified the second die, by erasing each face and writing a number of my own. Now, the sum of outcomes of the two dice is equally likely an integer between 1 and 12. Can you deduce the numbers written on the modified die? Note: For each dice, each face is equally likely to turn up after a toss. """ The unique solution is that die 2 is [0,0,0,6,6,6]. 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 ?=> nolog, N = 6, invisible_dice(N,D2), println(d2=D2), fail, nl. go => true. /* % Old and much more complex version go2 ?=> nolog, N = 6, % All tentative solutions invisible_dice2(N,[],Found), printf("Number of tentative solutions: %d\n", Found.len), Die1 = 1..6, % Find the one which has the same occurrences foreach(Die2 in Found) Map = new_map(), foreach(D1 in Die1, D2 in Die2) Sum = D1 + D2, Map.put(Sum, Map.get(Sum,0)+1) end, Freq = Map.values, Unique = Freq.remove_dups, if Freq.len == 12, Unique.len == 1 then println(die2=Die2), println(freq=Freq), println(unique=Unique) end end, nl. go2 => true. */ invisible_dice(N,D2) :- D1 = 1..N, % The normal die D2 = new_list(N), % The tampered die D2 :: 0..N, increasing(D2), % symmetry breaking foreach(V in 1..12) % lookup some index in D1 and D2 element(_D1Ix,D1,V1), element(_D2Ix,D2,V2), V #= V1 + V2 end, % Ensure that there are exact the same number of % occurrences for each sum of D1 and D2. Counts = new_list(12), foreach(I in 1..12) Counts[I] #= sum([ (D1[J] + D2[K]) #= I : J in 1..N, K in 1..N]), if I > 1 then Counts[I] #= Counts[I-1] end end, Vars = D2 ++ Counts, solve($[ff,split],Vars). /* % Old version invisible_dice2(N,Found1,Found) :- D1 = 1..N, % the normal die D2 = new_list(N), D2 :: 0..N, increasing(D2), % symmetry breaking % Weed out previous solutions foreach(F in Found1) sum([F[I] #!= D2[I] : I in 1..N]) #> 0 % sum([F[I] #= D2[I] : I in 1..N]) #< N % slower end, foreach(V in 1..12) % lookup some index in D1 and D2 element(_D1Ix,D1,V1), element(_D2Ix,D2,V2), V #= V1 + V2 end, Vars = D2, solve($[ff,split],Vars), invisible_dice2(N,Found1++[D2],Found). invisible_dice2(N,Found,Found). */