Prolog sublist

1

I want to create all the sublists of, for example, 3 elements of a list and also that these elements that it contains, before being added, fulfill a predicate. Example:

  

List: [11,12,9,8,7,6,5,3,2,4,15,16]
  condition: & 5;   sublist: [11,12,9] [9,8,7] [7,6,15] [16,11,12] [9,11,12] .....

All sublists of 3 elements that are greater than 5 for example.

This is what I have tried:

seleccionados(Lista,Sublista,Mayor):- findall(X,(member(X,Lista),X>Mayor),Sublista)
    
asked by FSlog 04.07.2016 в 09:47
source

2 answers

1

Applying the condition is independent of what you do next with the result. It's about applying a filter to the list and working with a new list, using exclude/3 . Now the question of getting all sublists of 3 elements:

sublistas(Lista,NumElementos,Resultado) :-
    length(Resultado,NumElementos),
    append(Aux,_Der,Lista),
    append(_Izq,Resultado,Aux).

Everything together:

condicion(N) :-
    N>5.

cosa_esta(Lista,N,Resultado):-
    exclude(Lista,condicion,ListaFiltrada),
    sublistas(ListaFiltrada,N,Resultado).

And the test:

?- cosa_esta([11,12,9,8,7,6,5,3,2,4,15,16],3,R).
R = [11, 12, 9] ;
R = [12, 9, 8] ;
R = [9, 8, 7] ;
R = [8, 7, 6] ;
R = [7, 6, 15] ;
R = [6, 15, 16] ;
false.
    
answered by 15.07.2016 в 13:10
1

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.
    
answered by 27.08.2016 в 04:02