mooly
mooly

Reputation: 113

Prolog summing first indices of lists

I'm new to Prolog, trying to sum up only the first elements of each list.

takeFirst([[1,2,3],[4,5,6],[7,8,9]],R).   --> R=1+4+7=12

It keeps outputting false and I don't understand what I'm missing here.

takeFirst([HF|_],[],HF):-!. 
takeFirst([H|L1],R):- H=[_|_], L1=[_|_],!,takeFirst(H,L1,NN), R is NN.
takeFirst([HF|_],[K|L2],HF):- takeFirst(K,L2,NN), HF is HF+NN. 

does anyone see what is wrong here?

Upvotes: 0

Views: 214

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476503

Well your code is rather chaotic: you define a takeFirst/3 first (that probably should be the base case?). Next you define two recursive cases, but you somehow pass the head the list in the recursive call, etc.

Actually the problem is easy to solve. You first better redirect your takeFirst/2 to a takeFirst/3` with an accumulator:

takeFirst(L,R) :-
    takeFirst(L,0,R).

Next we consider a base case: we reached the end of the list:

takeFirst([],R,R).

In this case we reached the end, and so the value of the accumulator, the variable we pass that keeps track of the sum thus far, is returned as the result.

In the recursive case, we are given a list [H|T] and we are interested in the head of the head HH so [[HH|_]|T]. In that case we add HH to the accumulator and do a recursive call with T:

takeFirst([[HH|_]|T],Ra,R) :-
    Rb is Ra+HH,
    takeFirst(T,Rb,R).

So putting it together we get:

takeFirst(L,R) :-
    takeFirst(L,0,R).

takeFirst([],R,R).
takeFirst([[HH|_]|T],Ra,R) :-
    Rb is Ra+HH,
    takeFirst(T,Rb,R).

Something that was not very clear in your question is what should be done if there is an empty list in your list, like [[1,2,3],[],[7,8,9]]. The above predicate will fail: it expects that all lists have at least one element. In case you simply want to ignore these lists, you can alter your code into:

takeFirst2(L,R) :-
    takeFirst2(L,0,R).

takeFirst2([],R,R).
takeFirst2([[]|T],Ra,R) :-
    takeFirst2(T,Ra,R).
takeFirst2([[HH|_]|T],Ra,R) :-
    Rb is Ra+HH,
    takeFirst2(T,Rb,R).

So we add a case where the list follows the pattern [[]|T], in which case we simply perform a recursive call with the tail T.

Based on the given above predicates, constructing a list of heads is not hard as well:

heads([],[])
heads([[HH|_]|TA],[HH|TB]) :-
    heads(TA,TB).

Upvotes: 1

Related Questions