简体   繁体   中英

Prolog - print the sum of the EVEN numbers from 1 to 10

I am trying to print all the even numbers from 1 to 10 using Prolog, and here is what I have tried:

printn(10,0):- write(10),!.
printn(X,Sum):- 
    ( X mod 2 =:= 0 -> Sum is X+Sum, Next is X+1, nl, printn(Next);
      Next is X+1, printn(Next) ).

but it returns false.

The most useful way of obtaining Prolog output is to capture the solution in a variable, either individually through backtracking, or in a list. The idea of "printing", which carries over from using other languages allows for formatting, etc, but is not considered the best way to express a solution.

In Prolog, you want to express your problem as a relation. For example, we might say, even_with_max(X, Max) is true (or succeeds) if X is an even number less than or equal to Max . In Prolog, when reasoning with integers, the CLP(FD) library is what you want to use.

:- use_module(library(clpfd)).

even_up_to(X, Max) :-
    X in 1..Max,
    X mod 2 #= 0,   % EDIT: as suggested by Taku
    label([X]).

This will yield:

3 ?- even_up_to(X, 10).
X = 2 ;
X = 4 ;
X = 6 ;
X = 8 ;
X = 10.

If you then want to collect into a list, you can use: findall(X, even_up_to(X), Evens).

What error do you have? Here is my solution:

  1. Create list [1...10]
  2. Filter it, excluding odd numbers
  3. Sum elements of the list

Code:

sumList([], 0).
sumList([Head|Tail], Sum) :-
   sumList(Tail, Rest),
   Sum is Head + Rest.

isOdd(X) :-
    not((X mod 2) =:= 0).

sumOfEvenNums(A, B, Out) :- 
    numlist(A, B, Numbers),
    exclude(isOdd, Numbers, Even_numbers),
    sumList(Even_numbers, Out).

Now you can call sumOfEvenNums(1, 10, N)

You don't need to create the list with the numbers from the beginning, it is better to examine numbers once:

print(X,Y):-print_even(X,Y,0).

print_even(X, X, Sum):- 
    (   X mod 2 =:= 0 -> Sum1 is X+Sum; 
        Sum1 = Sum
    ), print(Sum1).
print_even(X, Y, Sum):- 
    X<Y, Next is X+1,
    (   X mod 2 =:= 0 -> Sum1 is X+Sum, print_even(Next, Y, Sum1); 
        print_even(Next, Y, Sum)
    ).

Keep in mind that in Prolog Sum is Sum+1 always fails you need to use a new variable eg Sum1 .

Example:

?- print(1,10).
30
true ;
false.

In ECLiPSe, you can write with iterator:

sum_even(Sum):-
( for(I,1,10),fromto(0,In,Out,Sum)
    do
  (I mod 2 =:= 0 -> Out is In + I;Out is In)
)

With library(aggregate) :

evens_upto(Sum) :-
  aggregate(sum(E), (between(1, 10, E), E mod 2 =:= 0), Sum).

Thanks to @CapelliC for the inspiration.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM