You can get all the sublists of a list as if they were your power set, recursively. In the base case, the power set of an empty list []
is only the empty list:
sublists([],[]).
And the power set of a list with head and tail [X|Xs]
will be the lists of the set power of the tail Xs
, including and not including the head X
:
sublists([_|Xs],Ys) :- sublists(Xs,Ys).
sublists([X|Xs],[X|Ys]) :- sublists(Xs,Ys).
Now you can first filter the elements of the list that satisfy the predicate by include/3
, get the power set of the filtered list by sublists/2
, and stay with only the solutions of the desired size by length/2
:
sublists(Xs,Zs,S,P) :-
include(P,Xs,Ys),
length(Zs,S),
sublists(Ys,Zs).
For example, we define the predicates even/1
and lt5/1
that verify if a number is even or less than 5, respectively:
even(X) :- 0 is X mod 2.
lt5(X) :- X < 5.
And we get all the sublists of even numbers taken from 2 in 2 of the list [1,2,3,4,5,6]
:
?- sublists([1,2,3,4,5,6],Xs,2,even).
Xs = [4, 6] ;
Xs = [2, 6] ;
Xs = [2, 4] ;
false.
Or all sublists of numbers less than 5 taken from 3 in 3:
?- sublists([1,2,3,4,5,6],Xs,3,lt5).
Xs = [2, 3, 4] ;
Xs = [1, 3, 4] ;
Xs = [1, 2, 4] ;
Xs = [1, 2, 3] ;
false.