user2791841
user2791841

Reputation: 71

Counting the number of lists in a nested list

I am having troubles counting the number of lists in a nested list.

count_lists([H|T],R):-
   atomic(H),!,
   count_lists(T,NR),
   R is NR+1.
count_lists([[H|T]|Rest],R):-
   !,
   count_lists([H|T],R1),
   count_lists(Rest,R2),
   R is R1+R2.
count_lists([],0).

First of all, I try the basic case where an element in the list is atomic and thus, I should increment the counter by one. (Also, I tried removing the atomic predicate because I figured that because of it, my code will compute the number of elements in a nested list, but it still doesn't work) Then, if the first element is a list itself, I go recursively on it and on the remaining list, adding the results. And the third clause is states that the number of nested lists in an empty list is 0.

?count_lists([[1,5,2,4],[1,[4,2],[5]],[4,[7]],8,[11]],R).

should return 8 but instead, returns 12.

Upvotes: 0

Views: 1857

Answers (4)

I know it's been a while since you asked this, but here is the answer I think you were looking for:

count_lists([],1).
count_lists([H|T],Rez):-atomic(H),!,count_lists(T,Part),Rez is Part.
count_lists([H|T],Rez):-count_lists(H,Part1),count_lists(T,Part2),Rez is Part1+Part2.

This way, you count only the number of lists and not the number of elements within.

Upvotes: 2

Paulo Moura
Paulo Moura

Reputation: 18663

In your solution you forget that e.g. [1,2,3] = [1,2,3| []] or [1,2,3] = [1| [2| [3| []]]]. Thus, you're "over-counting", thanks to your first clause. For example:

?- count_lists([1,2,3], N).
N = 3.

But there's another problem. In your second clause, if you've a nested list that nests other lists, you don't count it. Not clear from the title if that's intended or if it's a bug.

Upvotes: 0

CapelliC
CapelliC

Reputation: 60004

you need to distinguish lists from other elements, i.e.

count_lists(E,R):-
    is_list(E),!,count_elems(E,N),
    R is N+1.
count_lists(_,0).

count_elems([H|T],R):-
    count_lists(H,Hc),
    count_elems(T,Tc),
    R is Hc+Tc.
count_elems([],0).

but the code is contrived, using library we can get it done in 1 step:

count_lists(E, R):-
    maplist(count_lists, E, Cs) -> sum_list(Cs, S), R is S+1 ; R = 0.

the code can be understood only WRT maplist/N behaviour

?- maplist(_,a).
false.

?- maplist(_,[]).
true.

?- maplist(_,[1]).
ERROR: apply:maplist_/2: Arguments are not sufficiently instantiated

Upvotes: 0

user3526304
user3526304

Reputation: 1

You shouldn't have complicated yourself.

count([],1).
count([L1|L2],Rez):- count(L1,Rez1),count(L2,Rez2),Rez is Rez1+Rez2.

You take out all the elements in a list recursively until you are left out with the empty list which values 1.

Upvotes: -1

Related Questions