[erlang-questions] Speedy unsort:shuffle/1,2 ?
Håkan Huss
huss01@REDACTED
Thu May 27 10:10:53 CEST 2010
On Thu, May 27, 2010 at 09:39, Johan Montelius <johanmon@REDACTED> wrote:
> On Thu, 27 May 2010 02:47:03 +0200, Toby Thain <toby@REDACTED>
> wrote:
>
>> It won't. Use Fisher-Yates or an equivalent method.
>> http://en.wikipedia.org/wiki/Fisher–Yates_shuffle
>
> Fisher-Yates (or the Knuth version) uses teh fact that you can access
> elements in an array and do the shuffling in O(n). If we have a list to
> shuffle the same algorithm will be O(n2) since we have to run down the list
> do find the element we want to shuffle.
>
> If we are working with lists I think any solutions is a version of
> merge-sort or quick-sort and have a O(n*lg(n)) complexity.
>
Indeed. The random merge that has been shown here earlier can be
corrected by replacing the coin flip with a choice that takes into
account the length of the lists:
-module(unsort).
-export([unsort/1]).
unsort(L) ->
unsort(L, length(L)).
unsort(L, Len) when Len < 2 ->
L;
unsort(L, Len) ->
L1_len = Len div 2,
L2_len = Len - L1_len,
{L1, L2} = lists:split(L1_len, L),
randmerge(unsort(L1, L1_len), L1_len, unsort(L2, L2_len), L2_len).
randmerge([], 0, L2, _) ->
L2;
randmerge(L1, _, [], 0) ->
L1;
randmerge(L1, L1_len, L2, L2_len) ->
case random:uniform(L1_len + L2_len) of
N when N =< L1_len ->
[hd(L1) | randmerge(tl(L1), L1_len - 1, L2, L2_len)];
_ ->
[hd(L2) | randmerge(L1, L1_len, tl(L2), L2_len - 1)]
end.
/Håkan
More information about the erlang-questions
mailing list