Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Newbie at loss

7 views
Skip to first unread message

Andreas

unread,
Nov 4, 2009, 2:03:49 PM11/4/09
to
Hi
I am trying to learn a bit of Prolog with the following simple proggie:

% If we list all the numbers below 10 that are multiples of 3 or 5,
% we get 3, 5, 6 and 9. The sum of these multiples is 23.
% Find the sum of all the multiples of 3 or 5 below 1000.

:- initialization(goal).

makeList(SL,[H|SL],_) :- H >= 1000.
makeList(L,[H|SL],Fak) :- Mult is H * Fak, makeList(L,[Mult,H,SL],Fak).

euler1(Sol) :-
makeList(L3,[3],3), makeList(L5,[5],5),
sumlist(L3,S3), sumlist(L5,S5), Sol is S3 + S5.

goal :-
% trace,
write('Euler Problem # 1'), nl,
% write('-----------------'), nl,
write('Solution: '), euler1(Sol), write(Sol).

But SWI-Prolog complains

ERROR: d:/prog/prolog/euler1.pl:9: Initialization goal raised exception:
ERROR: '.'/2: Type error: `[]' expected, found `[[81, [27, [9, [3,
[]]]]]]' ("x" must hold one character)
true.

I really can't figure out what is wrong. The error message is of no help
either as it does not indicate the line number.

Thanks for any hints
Andreas

bart demoen

unread,
Nov 4, 2009, 3:04:20 PM11/4/09
to
On Wed, 04 Nov 2009 20:03:49 +0100, Andreas wrote:

> Hi
> I am trying to learn a bit of Prolog with the following simple proggie:
>
> % If we list all the numbers below 10 that are multiples of 3 or 5, % we
> get 3, 5, 6 and 9. The sum of these multiples is 23. % Find the sum of
> all the multiples of 3 or 5 below 1000.
>
> :- initialization(goal).
>
> makeList(SL,[H|SL],_) :- H >= 1000.
> makeList(L,[H|SL],Fak) :- Mult is H * Fak, makeList(L,[Mult,H,SL],Fak).


the [Mult,H,SL] should be [Mult,H|SL]

make sure you understand why

I am not saying this solves all your problems, but it is essential

Cheers

Bart Demoen

Andreas

unread,
Nov 4, 2009, 3:35:26 PM11/4/09
to
bart demoen schrieb:

Thanks Bart
I hope to have got it now.
But would not [Mult|[H|SL]] have been better?
Andreas

bart demoen

unread,
Nov 4, 2009, 4:13:36 PM11/4/09
to
On Wed, 04 Nov 2009 21:35:26 +0100, Andreas wrote:

> But would not [Mult|[H|SL]] have been better? Andreas

?- [m|[h|s]] = [m,h|s].
true.

Two syntactic forms for the same thing.
Which one is "better" ?

Make sure you understand this - and if not ask.

Cheers

Bart Demoen

metaperl

unread,
Nov 5, 2009, 10:26:24 AM11/5/09
to
On Nov 4, 2:03 pm, Andreas <a....@nospam.org> wrote:
> Hi
> I am trying to learn a bit of Prolog with the following simple proggie:
>
> % If we list all the numbers below 10 that are multiples of 3 or 5,
> % we get 3, 5, 6 and 9. The sum of these multiples is 23.

the sum is 33 for numbers below 10.

metaperl

unread,
Nov 5, 2009, 10:27:36 AM11/5/09
to
On Nov 4, 2:03 pm, Andreas <a....@nospam.org> wrote:

> % Find the sum of all the multiples of 3 or 5 below 1000.

> Thanks for any hints

Thanks for the fun problem. With the help of the Prolog IRC channel
(particularly ski), here's the solution:

% Find the sum of all the multiples of 3 or 5 below 'maxNum'
% load and type goal(X) to run


maxNum(1000).

goal(Sum) :- getMults(Ns), sumNumbers(Ns, Sum).

validMultiple(N) :- N rem 5 =:= 0.
validMultiple(N) :- N rem 3 =:= 0.

neededNumber(X) :- maxNum(M), between(1,M, X), validMultiple(X).
getMults(Xs) :- bagof(X, neededNumber(X), Xs).


sumNumbers(Ns, Sum) :- sumNumbers_(Ns, 0, Sum).

sumNumbers_([], Acc, Acc).
sumNumbers_([Head|Tail], Acc, X) :- NewAcc is Acc + Head, sumNumbers_
(Tail, NewAcc, X).

metaperl

unread,
Nov 5, 2009, 10:30:53 AM11/5/09
to
supposedly the coding convention is camelCase for variables and
underscores in functor names. So I have rewritten it using that:

% Find the sum of all the multiples of 3 or 5 below 'maxNum'
% load and type goal(X) to run

max_num(1000).

valid_multiple(N) :- N rem 5 =:= 0.
valid_multiple(N) :- N rem 3 =:= 0.

needed_number(X) :- max_num(M), between(1,M, X), valid_multiple(X).
get_mults(Xs) :- bagof(X, needed_number(X), Xs).

goal(Sum) :- get_mults(Ns), sum_numbers(Ns, Sum).


sum_numbers(Ns, Sum) :- sum_numbers_(Ns, 0, Sum).

sum_numbers_([], Acc, Acc).
sum_numbers_([Head|Tail], Acc, X) :- NewAcc is Acc + Head, sum_numbers_
(Tail, NewAcc, X).

Cesar Rabak

unread,
Nov 5, 2009, 11:25:06 AM11/5/09
to
metaperl escreveu:
9 + 6 + 5 + 3 =:= 23.

Markus Triska

unread,
Nov 5, 2009, 12:27:24 PM11/5/09
to
metaperl <sche...@gmail.com> writes:

> here's the solution:

The following solution uses SWI-Prolog's library(clpfd):

?- N in 1..999, N mod 5 #= 0 #\/ N mod 3 #= 0,
findall(N, indomain(N), Ns), sum(Ns, #=, Sum).

yielding:

%@ Sum = 233168

For 1..1000, it yields 234168; your program instead yields 267333.

--
comp.lang.prolog FAQ: http://www.logic.at/prolog/faq/

metaperl

unread,
Nov 5, 2009, 3:25:50 PM11/5/09
to
On Nov 5, 12:27 pm, Markus Triska <tri...@logic.at> wrote:

> For 1..1000, it yields 234168; your program instead yields 267333.

yes, I was using bagof and getting repeats for numbers which where
divisible by both 3 and 5. It now yields the same result:

% Find the sum of all the multiples of 3 or 5 below 'maxNum'
% load and type goal(X) to run


goal(MaxNum, Sum) :- get_mults(MaxNum, Ns), sum_numbers(Ns, Sum).

get_mults(MaxNum, Xs) :- setof(X, needed_number(MaxNum, X), Xs).

needed_number(MaxNum, X) :- between(1,MaxNum, X), valid_multiple(X).

valid_multiple(N) :- N rem 5 =:= 0.
valid_multiple(N) :- N rem 3 =:= 0.

sum_numbers(Ns, Sum) :- sum_numbers_(Ns, 0, Sum).

sum_numbers_([], Acc, Acc).
sum_numbers_([Head|Tail], Acc, X) :- NewAcc is Acc + Head, sum_numbers_
(Tail, NewAcc, X).

deb :- visible(+all), leash(-exit).

0 new messages