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.
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)
).
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.
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).