Reputation: 213
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)
?
Upvotes: 3
Views: 373
Reputation: 12972
You could use library CLPFD :
:- use_module(library(clpfd)).
constraint_list([]).
constraint_list([H|T]):-H in 1..6 ,label([H]),constraint_list(T).
Examples:
?- constraint_list([X1,X2]).
X1 = X2, X2 = 2 ;
X1 = 2,
X2 = 3 ;
X1 = 2,
X2 = 4 ;
X1 = 2,
X2 = 5 ;
X1 = 3,
X2 = 2 ;
X1 = X2, X2 = 3 ;
X1 = 3,
X2 = 4 ;
X1 = 3,
X2 = 5 ;
X1 = 4,
X2 = 2 ;
X1 = 4,
X2 = 3 ;
X1 = X2, X2 = 4 ;
X1 = 4,
X2 = 5 ;
X1 = 5,
X2 = 2 ;
X1 = 5,
X2 = 3 ;
X1 = 5,
X2 = 4 ;
X1 = X2, X2 = 5.
?- L=[1,2,3] ,constraint_list(L).
false.
?- L=[2,2,3] ,constraint_list(L).
L = [2, 2, 3].
?- constraint_list(L).
L = [] ;
L = [2] ;
L = [2, 2] ;
L = [2, 2, 2] ;
L = [2, 2, 2, 2] ;
L = [2, 2, 2, 2, 2] ;
L = [2, 2, 2, 2, 2, 2] ;
L = [2, 2, 2, 2, 2, 2, 2] ;
L = [2, 2, 2, 2, 2, 2, 2, 2] ;
L = [2, 2, 2, 2, 2, 2, 2, 2, 2] ;
L = [2, 2, 2, 2, 2, 2, 2, 2, 2|...] ;
L = [2, 2, 2, 2, 2, 2, 2, 2, 2|...] ;
L = [2, 2, 2, 2, 2, 2, 2, 2, 2|...] ;
L = [2, 2, 2, 2, 2, 2, 2, 2, 2|...] ;
L = [2, 2, 2, 2, 2, 2, 2, 2, 2|...] .
... (and goes on)
Upvotes: 4
Reputation: 476574
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.
Upvotes: 7