Project Euler has a bunch of interesting mathematical programming challenges. I think they’re great for helping to learn a new language, and so will be using a few of the Euler problems to help me learn Erlang.
Here is the first problem.
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these is 23. Find the sum of all the multiples of 3 or 5 below 1000.
The problem is trivial, but it is ok to start easy. Here are three solutions; the third exploits Erlang message passing.
The first solution:
-module(p1).
-export([start/1]).
qualifies(N) ->
(N rem 3 == 0) or (N rem 5 == 0).
start() ->
Ans = lists:sum( lists:filter(fun qualifies/1, lists:seq(1,999))),
io:format("answer is ~p~n", [Ans]).
The second solution is similar, but syntactically more elegant. Use K=999.
-module(p1a).
-export([start/1]).
start(K) ->
Answer = lists:sum([ X || X <- lists:seq(1,K), (X rem 3 == 0) or (X rem 5 == 0) ]),
io:format("answer is ~p~n", [Answer]).
These two solutions are essentially the same. Out of curiousity, I ran the code for larger runs of integers. Both were ok for the ints 1…1000000 but choked when I went up to 10,000,000. The problem is the allocation of a list of 10,000,000 elements exhausted ram (other stuff was running). The third solution avoids the use of a huge list (all you Haskell guys are free to smirk and go on about lazy evaluation).
I made the solution a bit more general than the problem called for.
-module(ator1).
-export([start/1, genseq/1, genseq/2, genseq/3, accumulate/0, accumulate/1, accumulate/2]).
%% generate ints from 1 to N, inclusive
genseq(N) ->
genseq(1, N, 1).
%% generate ints K ... N
genseq(K, N) ->
genseq(K, N, 1).
%% generate ints from K, K+Delta, ... with upper bound N
genseq(K, N, Delta) ->
receive
{Pid, _} ->
if
K < N ->
Pid ! {self(), K},
genseq(K+Delta, N, Delta);
K == N ->
Pid ! {self(), K},
Pid ! {self(), done};
K > N ->
Pid ! {self(), done}
end
end.
ident(N) -> N.
filter(N) when (N rem 3== 0) ->N;
filter(N) when (N rem 5 == 0) ->N;
filter(_) ->0.
accumulate() ->
accumulate(0).
accumulate(Total) ->
accumulate(Total, fun ident/1).
accumulate(Total, Filter) ->
receive
{Pid, done} ->
io:format("total = ~p~n", [Total]);
{Pid, N} ->
Pid ! {self(), next},
accumulate(Total + Filter(N), Filter)
end.
start(N) ->
Seq = spawn(ator1, genseq, [N]),
Accumulate = spawn(ator1, accumulate, [0, fun filter/1]),
Seq ! {Accumulate, next}.

Posts