Liu Junhan
Liu Junhan

Reputation: 213

Prolog: Constraining the elements of a list to be within a range

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

Answers (2)

coder
coder

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

willeM_ Van Onsem
willeM_ Van Onsem

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

Related Questions