I'm trying to figure out how to create a predicate in prolog that sums the squares of only the even numbers in a given list.
Expected output:
?- sumsq_even([1,3,5,2,-4,6,8,-7], Sum).
Sum = 120 ;
false.
What I know how to do is to remove all the odd numbers from a list:
sumsq_even([], []).
sumsq_even([Head | Tail], Sum) :-
not(0 is Head mod 2),
!,
sumsq_even(Tail, Sum).
sumsq_even([Head | Tail], [Head | Sum]) :-
sumsq_even(Tail, Sum).
Which gives me:
Sum = [2, -4, 6, 8]
And I also know how to sum all the squares of the numbers in a list:
sumsq_even([], 0)
sumsq_even([Head | Tail], Sum) :-
sumsq_even(Tail, Tail_Sum),
Sum is Head * Head + Tail_Sum.
But I can't seem to figure out how to connect these two together. I'm thinking I may have gone the wrong way about it but I'm not sure how to define proper relationships to get it to make sense.
Thanks!
Split your problem into smaller parts. As you already said, you have two different functionalities that should be combined:
even
)sumsq
)So, in the first place, use different predicate names for different functionalities:
even([], []).
even([Head | Tail], Sum) :-
not(0 is Head mod 2),
!,
even(Tail, Sum).
even([Head | Tail], [Head | Sum]) :-
even(Tail, Sum).
sumsq([], 0).
sumsq([Head | Tail], Sum) :-
sumsq(Tail, Tail_Sum),
Sum is Head * Head + Tail_Sum.
In a third predicate you can now combine the two subsequent smaller steps:
sumsq_even(List, Sum) :-
even(List, Even_List),
sumsq(Even_List, Sum).
In this rule, first the (input) list is reduced to even elements (Even_List
) and after that the sum of the squares are calculated.
This is the result for your example:
sumsq_even([1,3,5,2,-4,6,8,-7], Sum).
S = 120.