Rares
Rares

Reputation: 33

Sum of even, product of odd numbers in Prolog

I have a list of numbers, I need to calculate the sum of the even numbers of the list and the product of the odd numbers of the same list. I'm new in Prolog, and my searches so far weren't successful. Can anyone help me solve it ?

l_odd_even([]). 
l_odd_even([H|T], Odd, [H|Etail]) :-
    H rem 2 =:=0,
    split(T, Odd, Etail). 
l_odd_even([H|T], [H|Otail], Even) :-
    H rem 2 =:=1,
    split(T, Otail, Even).

Upvotes: 3

Views: 5333

Answers (4)

repeat
repeat

Reputation: 18726

Use !

:- use_module(library(clpfd)).

Building on foldl/4, we only need to define what a single folding step is:

sumprod_(Z,S0,S) :-
   M #= Z mod 2,
   rem_sumprod_(M,Z,S0,S).

rem_sumprod_(0,Z,S0-P,S-P) :- 
   S0 + Z #= S.
rem_sumprod_(1,Z,S-P0,S-P) :- 
   P0 * Z #= P.

Let's fold sumprod_/3 over the list!

l_odd_even(Zs,ProductOfOdds,SumOfEvens) :-
   foldl(sumprod_,Zs,0-1,SumOfEvens-ProductOfOdds).

Sample query:

?- l_odd_even([1,2,3,4,5,6,7],Odd,Even).
Odd = 105,
Even = 12.

Alternatively, we can define sumprod_/3 even more concisely by using if_/3 and zeven_t/3:

sumprod_(Z,S0-P0,S-P) :-
   if_(zeven_t(Z), (S0+Z #= S, P0=P),
                   (P0*Z #= P, S0=S)).

Upvotes: 2

Nicholas Carey
Nicholas Carey

Reputation: 74197

It shouldn't get much simpler than

%
% invoke the worker predicate with the accumulators seeded appropriately.
%
odds_and_evens( [O]      , P , S ) :- odds_and_evens( [] , O , 0 , P , S ) .
odds_and_evens( [O,E|Ns] , P , S ) :- odds_and_evens( Ns , O , E , P , S ) .

odds_and_evens( []       , P , S , P , S  ) . % if the list is exhausted, we're done.
odds_and_evens( [O]      , X , X , P , S ) :- % if it's a single element list, we've only an odd element...
  P is X*O ,                                  % - compute it's product
  .                                           % - and we're done.
odds_and_evens( [O,E|Ns] , X , Y , P , S ) :- % if the list is at least two elements in length'e both an odd and an even:
  X1 is X*O ,                                 % - increment the odd accumulator
  Y1 is Y+E ,                                 % - increment the even accumulator
  odds_and_evens( Ns , X1 , Y1 , P , S )      % - recurse down (until it coalesces into one of the two special cases)
  .                                           % Easy!

Upvotes: 0

mvw
mvw

Reputation: 5105

Here is a suggestion for the sum of the even numbers from a list:

even(X) :- 
  Y is mod(X,2),       % using "is" to evaluate to number
  Y =:= 0.

odd(X) :-              % using even
  Y is X + 1,
  even(Y).

sum_even(0, []).       % empty list has zero sum
sum_even(X, [H|T]) :- 
  even(H),
  sum_even(Y, T), 
  X is Y+H.
sum_even(X, [H|T]) :- 
  odd(H),
  sum_even(X, T).      % ignore the odd numbers

Note: My Prolog has oxidized, so there might be better solutions. :-)

Note: Holy cow! There seems to be no Prolog support for syntax highlighting (see here), so I used Erlang syntax. Ha, it really works. :-)

Running some queries in GNU Prolog, I get:

| ?- sum_even(X,[]).    
X = 0 ?     
yes

| ?- sum_even(X,[2]).   
X = 2 ? 
yes

| ?- sum_even(X,[3]).    
X = 0 ? 
yes

| ?- sum_even(X,[5,4,3,2,1,0]).    
X = 6 ? 
yes

The ideas applied here should enable you to come up with the needed product.

Upvotes: 2

salva
salva

Reputation: 10234

untested!

sum_odd_product_even([], S, P, S, P).
sum_odd_product_even([H|T], S0, P0, S, P) :-
    S1 is S0 + H,
    sum_even_product_odd(T, S1, P0, S, P).

sum_even_product_odd([], S, P, S, P).
sum_even_product_odd([H|T], S0, P0, S, P) :-
    P1 is P0 * H,
    sum_odd_product_even(T, S0, P1, S, P).

sum_odd_product_even(L, S, P) :-
    sum_odd_product_even(L, 0, 1, S, P).

sum_even_product_odd(L, S, P) :-
    sum_even_product_odd(L, 0, 1, S, P).

Upvotes: 1

Related Questions