/* Global constraint k_same_modulo in Picat. From Global Constraint Catalogue http://www.emn.fr/x-info/sdemasse/gccat/Ck_same_modulo.html """ k_same_modulo(SETS, M) Purpose Given a collection of |SETS| sets, each containing the same number of domain variables, the k_same_modulo constraint enforces a same_modulo constraint between each pair of consecutive sets. Example ( < set-<1, 9, 1, 5, 2, 1>, set-<6, 4, 1, 1, 5, 5>, set-<1, 3, 4, 2, 8, 7> >, 3 ) The k_same_modulo constraint holds since: * The first and second collections of variables are assigned 1 value in {0, 3, ..., 3·k} , 3 values in {1, 4, ..., 1+3·k} and 2 values in {2, 5, ..., 2+3·k} . * The second and third collections of variables are also assigned 1 value in {0, 3, ..., 3·k} , 3 values in {1, 4, ..., 1+3·k} and 2 values in {2, 5, ..., 2+3·k} . """ 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, R = 3, V = new_array(R,N), V :: 1..9, M :: 2..9, % M = 3, V = {% {1,9,1,5,2,1}, % orig {_,9,1,5,2,1}, % test {6,4,1,1,5,5}, {1,3,4,2,8,7} }, k_same_modulo(V, M), Vars = V.vars ++ [M], solve(Vars), println(m=M), foreach(Row in V) println(Row.to_list) end, nl, fail, nl. % % from same_modulo.pi % same_modulo(V1,V2,M) => N = V1.len, MM = fd_max(M), M1 = new_list(N), M1 :: 0..MM-1, M2 = new_list(N), M2 :: 0..MM-1, GCC = new_list(MM), GCC :: 0..N, foreach(I in 1..N) M1[I] #= V1[I] mod M, M2[I] #= V2[I] mod M end, global_cardinality2(M1, GCC), global_cardinality2(M2, GCC). global_cardinality2(A, Gcc) => Len = length(A), Max = length(Gcc), Gcc :: 0..Len, foreach(I in 0..Max-1) count(I,A,#=,Gcc[I+1]) end. k_same_modulo(V, M) => foreach(I in 1..V.len, J in I+1..V.len) same_modulo([V[I, K] : K in 1..V[1].len], [V[J, K] : K in 1..V[1].len], M) end.