Reputation: 55
I'm still new to SWI-Prolog and I'm not sure how to do this two questions.
Write a predicate sum_composite(Numbers, Sum)
that sum ONLY COMPOSITE NUMBERS of a list of non-negative whole numbers. Example:
?- sumList([1,3,5,2,4,6,8,7],Sum).
Sum=18.
true
Write a predicate maxPrime(List, Min)
that given a list of numbers, returns the maximum prime element in the list. Example:
?- maxPrime([1, -4, 7, 4, 7, 9, -2, 3], Max).
Max = 7
true
This is what I have so far:
sum_list([],0). //empty list.
sum_list([First|Tail],Sum) :-
sumlist(Tail, SumTail).
Upvotes: 1
Views: 7339
Reputation: 783
question
composites_sum(NUMBERs, SUM)
that sums ONLY COMPOSITE NUMBERS of a list of non-negative whole numbers .(ed: a "composite" number is an number that is not an "prime" number) .
Example :
?- composites_sum([1,3,5,2,4,6,8,7],Sum) .
Sum = 18 .
true
answer
./src/parts/composites_sum.prolog
composites_sum(NUMBERs0,SUM)
:-
composites(NUMBERs0,NUMBERs) ,
sum(NUMBERs,SUM)
.
?- composites_sum([1,3,5,2,4,6,8,7],SUM) .
SUM = 18 .
?- composites_sum([1,2,3],SUM) .
SUM = 0 .
?- sum([1,2,3],SUM) .
SUM = 6 .
?- sum([1,2,3,4],SUM) .
SUM = 10 .
?- composites_sum([1,2,3,4],SUM) .
SUM = 4 .
?- composites_sum([],SUM) .
SUM = 0 .
%! prime(N0)
%
% true if `N0` is an prime number ;
% false if `N0` is not an prime number .
%
% this predicate can be used to generate prime numbers ;
% see the demos for the example using `between` .
/*
If an number is divisible by any other number less than it's sqrt then
the number is not prime ; otherwise it is prime .
*/
:- op(1,'xfy','prime_') .
prime(N0) :- [start] prime_ (N0) .
[start] prime_ (N0)
:-
[init] prime_ (N0)
.
[init] prime_ (N0)
:-
K is floor(sqrt(N0)) ,
[while] prime_ (N0,K)
.
[while] prime_ (_N0,K0)
:-
K0 = 1 ,
! ,
[finish] prime_ (true)
.
[while] prime_ (N0,K0)
:-
0 is mod(N0,K0) , % true if K0 multiplied by some value is N0 .
! ,
[finish] prime_ (false)
.
[while] prime_ (N0,K0)
:-
! ,
K is K0 - 1 ,
[while] prime_ (N0,K)
.
[finish] prime_ (true) .
[finish] prime_ (false) :- false .
?- prime(1) .
true
?- prime(2) .
true
?- prime(3) .
true
?- prime(4) .
false
?- prime(5) .
true
?- prime(7) .
true
?- between(1,1000,N) , prime(N) .
N = 1 ? ;
N = 2 ? ;
N = 3 ? ;
N = 5 ? ;
N = 7 ? ;
N = 11 ? ;
N = 13 ? ;
N = 17 ? ;
N = 19 ? ;
N = 23 ? ;
N = 29 ? ;
N = 31 ? ;
N = 37 ? ;
N = 41 ? ;
N = 43 ? ;
N = 47 ? ;
N = 53 ? ;
N = 59 ? ;
N = 61 ? ;
N = 67 ? ;
N = 71 ? %etcetera.
%! composites(Xs0,Ys)
%
% `Ys` is those elements of `Xs0` that are not prime .
composites([],[]) :- ! .
composites([X0|Xs],[X0|Ys])
:-
+ prime(X0) ,
! ,
composites(Xs,Ys)
.
composites([_X0|Xs],Ys0)
:-
! ,
composites(Xs,Ys0)
.
?- composites([1,2,3,4,5,6,7,8,9,10,11,12],Cs) .
Cs = [4,6,8,9,10,12] .
?- composites([1],Cs) .
Cs = [] .
?- composites([],Cs) .
Cs = [] .
%! sum(Xs,SUM)
%
% calculate the total sum of the items of list `Xs` .
sum(Xs,SUM)
:-
sum(Xs,0,SUM)
.
sum([],SUM0,SUM0) .
sum([X0|Xs],SUM0,SUM)
:-
SUM1 is SUM0 + X0 ,
sum(Xs,SUM1,SUM)
.
?- sum([1,2,3,4],SUM).
SUM = 10.
?- sum([1,2],SUM).
SUM = 3.
?- sum([1,2,-1],SUM).
SUM = 2.
?- sum([-1],SUM).
SUM = -1.
?- sum([],SUM).
SUM = 0.
Upvotes: 0
Reputation: 476503
As nearly always in Prolog, you can write predicates on lists using two clauses.
foo(L,R) :-
foo(L,I,R).
foo([],F,F).
foo([H|T],F,R) :-
F2 is f(F,H),
foo(T,F2,R).
With F
the current result, F2
the updated result, H
the head of the list that far, T
the tail of the list, I
the initial value, and R
the result.
Such patterns use tail recursion with an accumulator (in this case F
), this patterns are considered one of the most efficient in Prolog. (middle-recursion or return accumulators increase the call stack and require more bookkeeping).
In case of a sum, this is tranformed into:
sum(L,R) :-
sum(L,0,R).
sum([],F,F).
sum([H|T],F,R) :-
F2 is F+H,
sum(T,F2,R).
I will leave the maxPrime
as an exercise, but it fits "nicely" into the above described pattern.
Upvotes: 1