ListsfromList function in Prolog

Viewed 90

I writing a predicate in prolog in which I give two parameters listsFromL(X,B). X would be a list with lists within that list and B would be a new list with the lists from X.

So, for example, if I would call listsFromL([1,2,[d,a]],X). the return would be B = [[d,a]]. and if I would add more lists to X I would get a longer list with lists as X.

How do I go about this?

3 Answers

You need:

  1. A predicate to filter you original list: one which detects lists: is_list/1
  2. A "higher-order" predicate that, given the above, filters a list which may contains lists into a list with only the lists: include/3

Now you just need to put those two Lego blocks together.

listsFromList(Stuff,OnlyLists) :-
   include(is_list,Stuff,OnlyLists).

And so:

?- listsFromList([],OLs).
OLs = [].

?- listsFromList([a,b,c],OLs).
OLs = [].

?- listsFromList([a,b,[x,y],c],OLs).
OLs = [[x, y]].
listsFromList([],[]) .

listsFromList([HEAD|SOURCEs],[HEAD|TARGETs])
:-
is_list(HEAD) ,
listsFromList(SOURCEs,TARGETs)
.

listsFromList([HEAD|SOURCEs],TARGETs)
:-
\+ is_list(HEAD) ,
listsFromList(SOURCEs,TARGETs)
.
/*
?- listsFromList([1,2,3,4,[a,b]],X).
X = [[a, b]] ;
false.

?- listsFromList([1,[a,b],2,[c,d],3],X).
X = [[a, b], [c, d]] ;
false.

?- listsFromList([],X).
X = [].

?- 
*/
listsFromList(SOURCEs,TARGETs)
:-
phrase(listsFromList_,SOURCEs,TARGETs)
.

listsFromList_,[] --> \+ [_] .

listsFromList_,[ITEM] --> [ITEM] , { is_list(ITEM) }  , listsFromList_ .

listsFromList_,[] --> [ITEM] , { \+ is_list(ITEM) } , listsFromList_ .
/*

?- listsFromList([1,2,3,4,[a,b]],X).
X = [[a, b]] ;
false.

?- listsFromList([1,2,[b,c],3,4,[a,b]],X).
X = [[b, c], [a, b]] ;
false.

?- listsFromList([],X).
X = [] ;
false.

?- 
*/
Related