Reza Moussavi
unread,Oct 31, 2010, 8:11:58 PM10/31/10Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Sign in to report message
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
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.