[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