Fibonacci monitoring (for fun)

19 views
Skip to first unread message

Reza Moussavi

unread,
Oct 31, 2010, 8:11:58 PM10/31/10
to Erlang Programming
Hi,
I send a problem to some student;
write a module to calculate fibonacci of a list of numbers in parallel
BUT provide a functionality to show the progress while user waiting
for results.

Here is my solution
Send your solutions if you wish.


---------------------

-module(new_fib).
-export([fib/2,mon_res/1,mon_perc/2]).

%% try these on shell:
%% new_fib:fib([37,33,36,29,12,38,31,10,39,32,37,35],result).
%% new_fib:fib([37,33,36,29,12,38,31,10,39,32,37,35],percent).

calc_fib(0)->0;
calc_fib(1)->1;
calc_fib(N) when N>1 -> calc_fib(N-1)+calc_fib(N-2).

fib([],_Cmd)->[];
fib(L,result)->
{N,_Total,Results}=spawnall(L,1,0,[]),
Monitor=spawn(?MODULE,mon_res,[Results]),
receiveall(N,Results,Monitor);
fib(L,percent)->
{N,Total,Results}=spawnall(L,1,0,[]),
Monitor=spawn(?MODULE,mon_perc,[Total,0]),
receiveall(N,Results,Monitor);
fib(_L,_Cmd)->
{unknown_command,{valid_commands,[result,percent]}}.

spawnall([],N,Total,Results)-> {N-1,Total,lists:reverse(Results)};
spawnall([H|T],N,Total,Results)->
F=fun()->receive {request,Pid,Num,Index}->Pid!
{result,Index,Num,calc_fib(Num)} end end,
spawn(F)!{request,self(),H,N},
spawnall(T,N+1,Total+H,[{N,processing,H}|Results]).

mon_perc(Total,Done)->
io:format("~w~n",[trunc(Done*100/Total)]),
receive
{update,_Res,N}->
mon_perc(Total,Done+N);
stop->
io:format("~w~n",[monitor_stopped])
after 2000->
mon_perc(Total,Done)
end.

mon_res(Results)->
io:format("~s~n",[mon_conv(Results)]),
receive
{update,Res,_N}->
mon_res(Res);
stop->
io:format("~w~n",[monitor_stopped])
after 2000->
mon_res(Results)
end.

mon_conv([])->[];
mon_conv([{_I,done,_N,_Fib}|T])->
[35|mon_conv(T)];
mon_conv([{_I,processing,_N}|T])->
[95|mon_conv(T)].

rawres([])->[];
rawres([{_Index,done,_N,Fib}|T])->
[Fib|rawres(T)];
rawres([H|T])->
[{error,H}|rawres(T)].

receiveall(0,Results,Monitor)->
Monitor!stop,
rawres(Results);
receiveall(I,Results,Monitor)->
receive
{result,Index,N,Fib}->
Res=lists:keyreplace(Index,1,Results,{Index,done,N,Fib}),
Monitor!{update,Res,N},
receiveall(I-1,Res,Monitor)
end.
Reply all
Reply to author
Forward
0 new messages