tags:

views:

298

answers:

3

I'm trying to make a function that has a list of lists, it multiplies the sum of the inner list with the outer list. So far i can sum a list, i've made a function sumlist([1..n],X) that will return X = (result). But i cannot get another function to usefully work with that function, i've tried both is and = to no avail.

+1  A: 

The part "it multiplies the sum of the inner list with the outer list" isn't really clear, but I believe you mean that, given a list [L1,...,Ln] of lists of numbers, you want to calculate S1*..*Sn where Si is the sum of the elements in Li (for each i).

I assume the existence of plus and mult with their obvious meaning (e.g. plus(N,M,R) holds precisely when R is equal to N+M). First we need predicate sum such that sum(L,S) holds if, and only if, S is the sum of the elements of L. If L is empty, S obviously must be 0:

sum([],0).

If L is not empty but of the form [N|L2], then we have that S must be N plus the sum S2 of the elements in L2. In other words, we must have both sum(L2,S2) (to get S2 to be the sum of the elements of L2) and plus(N,S2,S). That is:

sum([N|L2],S) :- sum(L2,S2), plus(N,S2,S).

In the same way you can figure out the predicate p you are looking for. We want that p(L,R) holds if, and only if, R is the product of S1 through Sn where L=[L1,...,Ln] and sum(Li,Si) for all i. If L is empty, R must be 1:

p([],1).

If L is not empty but of the form [LL|L2], then we have that R must be the product of 'S', the sum of the elements of LL, and 'P', the product of the sums of the lists in L2. For S we have already have sum(LL,S), so this gives us the following.

p([LL|L2],R) :- sum(LL,S), p(L2,P), mult(S,P,R).

One thing I would like to add is that it is probably not such a good idea to see these predicates as functions you might be used to from imperative or functional programming. It is not the case that sumlist([1,..,n],X) returns X = (result); (result) is a value for X such that sumlist([1,...,n],X) is true. This requires a somewhat different mindset. Instead of thinking "How can I calculate X such that p(X) holds?" you must think "When does P(X) hold?" and use the answer ("Well, if q(X) or r(X)!") to make the clauses (p(X) :- q(X) and p(X) :- r(X)).

mweerden
+1  A: 

Is this what you mean?

prodsumlist([], 1).

prodsumlist([Head | Tail], Result) :-
    sumlist(Head, Sum_Of_Head),
    prodsumlist(Tail, ProdSum_Of_Tail),
    Result is Sum_Of_Head * ProdSum_Of_Tail.

where sumlist/2 is a SWI-Prolog built-in.

Usage example:

?- prodsumlist([[1, 2], [3], [-4]], Result).
Result = -36.
Kaarel
A: 

Here is a rewrite of Kaarel's answer (that's the intention anyway!) but tail-recursive.

prodsumlist(List, Result) :-
    xprodsumlist(List,1,Result).

xprodsumlist([],R,R).

xprodsumlist([Head|Rest],Sofar,Result) :-
    sumlist(Head, Sum_Of_Head),
    NewSofar is Sofar * Sum_Of_Head,
    xprodsumlist(Rest, NewSofar, Result).
pfctdayelise