thegalah
thegalah

Reputation: 528

Prolog recursive program returning too many results

I have a Prolog program which is meant to find the sum of the squares of all the numbers in a list divisible by three or five. However it returns more than one result and I'm not sure why.

% --divisibility tests--

div_test(N):-
    % divisible by three?
    0 is N mod 3.
div_test(N):-
    % divisible by five?
    0 is N mod 5.

% sum of an empty list is zero (base case)
square_sum([], Sum):-
    Sum is 0.

% --recursive cases
square_sum([Head | Tail], Sum) :-
    div_test(Head),
    square_sum(Tail, TempSum),
    Sum is Head*Head + TempSum.

square_sum([Head | Tail], Sum) :-
    square_sum(Tail, TempSum),
    Sum is TempSum.

Given the following input:

?-square_sum([1,2,3,4,5],Sum).

I get the following output:

Sum = 34 ;
Sum = 9 ;
Sum = 25 ;
Sum = 0.

34 is the only output I should get

Upvotes: 1

Views: 528

Answers (1)

joel76
joel76

Reputation: 5645

% --recursive cases
square_sum([Head | Tail], Sum) :-
    div_test(Head),
    square_sum(Tail, TempSum),
    Sum is Head*Head + TempSum.

square_sum([Head | Tail], Sum) :-
    square_sum(Tail, TempSum),
    Sum is TempSum.

In the second rule you don't test if div_test succeeds. You can either add a cut (!) after div_test(Head), in the first rule or add \+div_test(Head), in the second rule.

You use SWI-Prolog, so you can use module lambda.pl found there http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl and write

:- use_module(library(lambda)).
div_test(N):-
    % divisible by three?
    0 is N mod 3.
div_test(N):-
    % divisible by five?
    0 is N mod 5.

square_sum(Lst, Sum) :-
    foldl(\X^Y^Z^((div_test(X); div_test(X))
              ->  Z is Y + X*X
              ;   Z = Y), Lst, 0, Sum).

Upvotes: 2

Related Questions