Wog12222
Wog12222

Reputation: 35

how to detect a list of lists in Prolog?

lol([]).
lol([H|T]) :- lol(T).
lol([H|T]) :- lol(H).

I tried using this, but it returns true even for a normal 1d list. how to get exactly true for 2d list? Or list in a list.

Upvotes: 2

Views: 630

Answers (2)

Reema Q Khan
Reema Q Khan

Reputation: 878

1- lil predicate will check how many inner lists we have. If greater than 0 than return true, else false.

2- is_list built-in will check each H if it is a list.

3- Count will count each time is_list finds a list.

4- sum predicate simply sums the count list, i.e. [1,1,1] = 3.

lil([H|T]):-
    Count=1,
    lil1([H|T],Count,TotalCount),
    sum(TotalCount,Sum),
    Sum>0.

lil1([],_,[]).
lil1([H|T],Count,[Count|List]):-
   is_list(H),
    Count1 is Count+0,
    lil1(T,Count1,List).

sum([],0).
sum([H|T],S):-
    sum(T,S1),
    S is S1+H.

Example:

?- lil([]).
false

?- lil([[w],[v,v,v]]).
true

?- lil([a,n,b,b]).
false

?- lil([[w],[v,v,v],s]).
false

?- lil([[w],[v,v,v],[s,s,s,s]]).
true

?- lil([[w]]).
true

Upvotes: 0

David Tonhofer
David Tonhofer

Reputation: 15316

How about this:

A list has the "list of list" quality if and only if all of its elements are lists.

Or in code, where we relax the "if and only if" equivalence to "if", which is good enough for our purposes:

% A vacuous truth:
% The empty list can be considered a list-of-lists as it contains 
% nothing at all

list_of_lists([]).              

% A list with at head element E is a list-of-lists if E is a list
% and and the Rest of the list is a list-of-lists.

list_of_lists([E|Rest]) :- actually_a_list(E), list_of_lists(Rest).

What's this actually_a_list(E)? It's where we test whether E is actually a list.

% The empty list is actually a list

actually_a_list([]).              

% A list with at head element we don't care about and name `_`
% is actually a list if the Rest of the list is actually a list

actually_a_list([_|Rest]) :- actually_a_list(Rest).

And so:

?- list_of_lists([]).             % certainly a list-of-lists
true.

?- list_of_lists(foo).            % clearly not a list, and not a list-of-lists
false.

?- list_of_lists([a,b,c]).        % a list but not a list-of-lists 
false.

?- list_of_lists([[a],[b,c]]).    % here is one!
true.

?- list_of_lists([[a],x,[b,c]]).  % nope
false.

?- list_of_lists([a,b|c]).        % this is not even a list
false.

In case we give the predicate an "open list" which has an unbound ending, in generates trivial endings containing only open lists:

?- list_of_lists([[a,b],[c,d]|Fin]).
Fin = [] ;
Fin = [[]] ;
Fin = [[], []] ;
Fin = [[], [], []] 
...

or perhaps clearer:

?- L=[[a,b],[c,d]|_],list_of_lists(L).
L = [[a, b], [c, d]] ;
L = [[a, b], [c, d], []] ;
L = [[a, b], [c, d], [], []] ;
L = [[a, b], [c, d], [], [], []] ;
L = [[a, b], [c, d], [], [], [], []] ;
L = [[a, b], [c, d], [], [], [], [], []] 
...

Upvotes: 3

Related Questions