Are there any ways to constrain the elements of a list to be within a range, something that would look more like 1-6
, instead of using between(1, 6, X)
?
The clpfd
library, has an ins/2
predicate, where you can specify - for a list of variables - the range of the elements.
Like:
all_between(Low, High, Vars) :-
Vars ins Low..High.
When calling all_between(1,6,[X1,X2,X3]).
we get:
X1 in 1..6,
X2 in 1..6,
X3 in 1..6.
In case we want to enumerate over the elements, we can use label(L).
as well, to assign values:
all_between_enumerate(Low, High, Vars) :-
Vars ins Low..High,
label(Vars).
For all_between_enumerate(1,2,[X1,X2,X3]).
this generates:
?- all_between_enumerate(1,2,[X1,X2,X3]).
X1 = X2, X2 = X3, X3 = 1 ;
X1 = X2, X2 = 1,
X3 = 2 ;
X1 = X3, X3 = 1,
X2 = 2 ;
X1 = 1,
X2 = X3, X3 = 2 ;
X1 = 2,
X2 = X3, X3 = 1 ;
X1 = X3, X3 = 2,
X2 = 1 ;
X1 = X2, X2 = 2,
X3 = 1 ;
X1 = X2, X2 = X3, X3 = 2.
In case you already added constraints to the variables, like X1 #< X3
, these are taken into account as well:
?- X1 #< X3, all_between_enumerate(1,2,[X1,X2,X3]).
X1 = X2, X2 = 1,
X3 = 2 ;
X1 = 1,
X3 = X2, X2 = 2.