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

Johan Montelius johanmon@REDACTED
Thu May 27 11:52:52 CEST 2010


> Contrast this with the version that takes into account the length of  
> both lists.
>
> Julian

Very interesting, I didn't think about that. The same problem does not  
occur in my qsort version does it?

Come to think of it I don't think my version is guaranteed to terminate.  
If we are extremely unlucky the split will generate one empty lists and  
one list with all elements in it :-0

well, for those of you who like living on the edge here is a rewrite that  
(if it terminates:-) is quite quick.


shuffle(L)  ->
      shuffle(L, [], <<>>, rbit(12345), []).
  	
shuffle([], R, B, S, Sofar) -> {R, B, S, Sofar};
shuffle([I], R, B, S, Sofar) -> {R, B, S, [I|Sofar]};
shuffle(L, Rnd, Bin, Seed, Sofar) ->
      {R1, B1, S1, L1, L2} = split(L, Rnd, Bin, Seed, [], []),
      {R2, B2, S2, Q1} = shuffle(L1, R1, B1, S1, Sofar),
      shuffle(L2, R2, B2, S2, Q1).


split([], Rnd, Bin, Seed, L1, L2) ->
      {Rnd, Bin, Seed, L1, L2};
split([H|T], [R|Rnd], Bin, Seed, L1, L2) ->
      case R of
	0 ->
	    split(T, Rnd, Bin, Seed, [H|L1], L2);
	1 ->
	    split(T, Rnd, Bin, Seed, L1, [H|L2])
      end;
split(L, [], Bin, Seed, L1, L2) ->
     {Rnd, Rest, New} = rbit(Bin, Seed),
     split(L, Rnd, Rest, New, L1, L2).

rbit(Seed) ->
     crypto:start(),
     <<Seed>>.

rbit(<<>>, Seed) ->
     Bin = crypto:md5(Seed),
     rbit(Bin, Bin);
rbit(<<B1:1,B2:1,B3:1,B4:1,B5:1,B6:1,B7:1,B8:1, Rest/binary>>, Seed) ->
     {[B1,B2,B3,B4,B5,B6,B7,B8], Rest, Seed}.



-- 
Associate Professor Johan Montelius
Royal Institute of Technology - KTH
School of Information and Communication Technology - ICT


More information about the erlang-questions mailing list