/* Global constraint range_ctr in Picat. From Global Constraint Catalogue http://www.emn.fr/x-info/sdemasse/gccat/Crange_ctr.html """ Constraint range_ctr​(VARIABLES,​CTR,​VAR)​ Purpose Constraint the difference between the maximum value and the minimum value of a set of domain variables. More precisely, let R denote the difference between the largest and the smallest variables of the VARIABLES collection. Enforce the following constraint to hold: R CTR VAR. Example (<1,9,4>,=,8) The range_ctr constraint holds since its last argument VAR=8 is equal (i.e., CTR is set to =) to max(1,9,4)-min(1,9,4). """ 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 = 3, Ctr = 0, Variables = new_list(N), Variables :: 1..9, TVar :: 1..9, Variables = [1,9,4], % TVar = 8, range_ctr(Variables, Ctr, TVar), Vars = Variables ++ [TVar], solve(Vars), println(variables=Variables), println(tvar=TVar), println(ctr=Ctr), nl, fail, nl. % Ctr is also a decision variable go2 => N = 3, Variables = new_list(N), Variables :: 1..9, TVar :: 1..9, Ctr :: -2..3, Variables = [1,9,4], TVar = 8, range_ctr2(Variables, Ctr, TVar), Vars = Variables ++ [TVar,Ctr], solve(Vars), println(variables=Variables), println(tvar=TVar), nl, fail, nl. range_ctr(Variables, Ctr, TVar) => MMin #= min(Variables), MMax = max(Variables), Res #= MMax - MMin, cmp(TVar, Res, Ctr). % Ctr is also a decision variable range_ctr2(Variables, Ctr, TVar) => MMin #= min(Variables), MMax = max(Variables), Res #= MMax - MMin, cmp2(TVar, Res, Ctr). % % Since Picat don't handle function variables we use the following % hack where T is the type of comparison operator. % T: % - 2 : a < b % - 1 : a <= b % 0 : a = b % 1 : a >= b % 2 : a > b % else : a != b % cmp(A, B, T) => if T == -2 then A #< B elseif T == -1 then A #<= B elseif T == 0 then A #= B elseif T == 1 then A #>= B elseif T == 2 then A #> B else A #!= B end. % Let T be a variable as well cmp2(A, B, T) => T #= -2 #=> A #< B, T #= -1 #=> A #<= B , T #= 0 #=> A #= B, T #= 1 #=> A #>= B, T #= 2 #=> A #> B, T #> 3 #=> A #!= B.