/* Global constraint inverse within range in Picat. From Global Constraint Catalogue http://www.emn.fr/x-info/sdemasse/gccat/Cinverse_withing_range.html """ inverse_within_range​(X,​Y) Purpose If the ith variable of the collection X is assigned to j and if j is less than or equal to the number of items of the collection Y then the jth variable of the collection Y is assigned to i. Conversely, if the jth variable of the collection Y is assigned to i and if i is less than or equal to the number of items of the collection X then the ith variable of the collection X is assigned to j. Example ( <9, 4, 2>, <9, 3, 9, 2> ) Since the second item of X is assigned to 4, the fourth item of Y is assigned to 2. Similarly, since the third item of X is assigned to 2, the second item of Y is assigned to 3. Figure 4.150.1 illustrates the correspondence between X and Y. X Y 1 9 9 1 2 4 3 2 3 2 9 3 2 4 Figure 4.150.1. Correspondence between the items of X=<9, 4, 2> and the items of Y=<9, 3, 9, 2> """ 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 => N1 = 3, N2 = 4, X1 = new_list(N1), X1 :: 1..9, % [1,2,3,4,9], X2 = new_list(N2), X2 :: 1..9, % [1,2,3,9], X1 = [9,4,2], X2 = [9,3,9,2], inverse_within_range(X1, X2), Vars = X1 ++ X2, solve(Vars), println(x1=X1), println(x2=X2), nl, fail, nl. inverse_within_range(X1, X2) => N1 = X1.len, N2 = X2.len, foreach(I in 1..N1) X1[I] #<= N2 #<=> sum([X2[J] #= I #/\ X1[I] #= J : J in 1..N2]) #> 0 end, foreach(J in 1..N2) X2[J] #<= N1 #<=> sum([X1[I] #= J #/\ X2[J] #= I : I in 1..N1]) #> 0 end.