[erlang-questions] Speedy unsort:shuffle/1,2 ?

Johan Montelius johanmon@REDACTED
Wed May 26 23:15:04 CEST 2010


ok, kids are a sleep, here is my go. The random function can be replaced  
to just about anything. My only worries is that it is generating a lot of  
garbage.


%%  copy right, creative commons

-module(unsort).
-export([shuffle/1, shuffle/2]).

shuffle(Is) when is_list(Is) ->
     shuffle(Is, generator(12345)).

shuffle(Is, F) ->
     shuffle(Is, F, []).
	
shuffle([], F, Sofar) -> {F, Sofar};
shuffle([I], F, Sofar) -> {F, [I|Sofar]};
shuffle(Is, F, Sofar) when is_list(Is), is_function(F) ->
     {F1, S1, S2} = split(Is, F, [], []),
     {F2, Q1} = shuffle(S1, F1, Sofar),
     shuffle(S2, F2, Q1).

split([], F, L1, L2) ->
     {F, L1, L2};
split([H|T], F, L1, L2) ->
     case F() of
	{0, F1} ->
	    split(T, F1, [H|L1], L2);
	{1, F1} ->
	    split(T, F1, L1, [H|L2])
     end.


%% generator should return a function F, that when applied F() returns a  
tuple
%% {R, F1} wher R is 0 or 1 and F1 a new function with the same property.

generator(Seed) ->
     crypto:start(),
     fun() ->
	    rbit([], <<>>, fun() -> rnd(<<Seed>>) end)
     end.

rbit([], <<>>, F) ->
     {Bin, F1} = F(),
     rbit([], Bin, F1);
rbit([], Bin, F) ->
     <<B1:1,B2:1,B3:1,B4:1,B5:1,B6:1,B7:1,B8:1, Rest/binary>> = Bin,
     rbit([B1,B2,B3,B4,B5,B6,B7,B8], Rest, F);
rbit([R|Rest], Bin, F) ->
     {R, fun() -> rbit(Rest, Bin, F) end}.

rnd(Seed) ->
     Bin = crypto:md5(Seed),
     {Bin, fun() -> rnd(Bin) end}.
	


-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


More information about the erlang-questions mailing list