/* Uniform dice in Picat. This model generates two dice with uniform distribution of the sums. Example: for N = 6, Min = 1, Max = 6: dist: [0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6] x1[2, 2, 4, 4, 6, 6] x2[5, 5, 5, 6, 6, 6] 7: 6 8: 6 9: 6 10: 6 11: 6 12: 6 For N = 6 and Min = 0, Max = 6: dist = [3,3,3,3,3,3,3,3,3,3,3,3] x1 = [0,0,0,6,6,6] x2 = [1,2,3,4,5,6] 1: 3 2: 3 3: 3 4: 3 5: 3 6: 3 7: 3 8: 3 9: 3 10: 3 11: 3 12: 3 Cf uniform_dice2.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 => N = 6, MinVal = 0, MaxVal = 6, % max integer % MaxVal = 10, % max integer uniform_dice(N,MinVal,MaxVal, Dist,X1,X2,Z), println(z=Z), println(dist=Dist), println(x1=X1), println(x2=X2), foreach(I in 1..Dist.len, Dist[I] > 0) printf("%2d: %3d\n", I,Dist[I]) end, nl, fail, nl. go => true. uniform_dice(N,MinVal,MaxVal, Dist,X1,X2,Z) => % the two dice X1 = new_list(N), X1 :: MinVal..MaxVal, X2 = new_list(N), X2 :: MinVal..MaxVal, Dist = new_list(MaxVal*2), Dist :: 0..N*N, % number of dists > 0 Z #= sum([Dist[K] #> 0 : K in 1..MaxVal*2]), foreach(K in 1..MaxVal*2) Dist[K] #= sum([X1[I]+X2[J] #= K : I in 1..N, J in 1..N]) end, same_except_0(Dist), % symmetry breaking increasing(X1), increasing(X2), lex_le(X1,X2), % redundant constraints N*N mod Dist[MaxVal*2] #= 0, N*N mod Z #= 0, sum(Dist) #= N*N, Vars = X1 ++ X2, % ++ Dist, solve($[min,split],Vars). % same_except_0: either a value is 0 or is the same values same_except_0(X) => foreach(K in 1..X.len-1) X[K] #= 0 #\/ (X[K] #= X[K+1]) end.