Skip to content

Instantly share code, notes, and snippets.

@decoda
Last active June 26, 2023 08:02
Show Gist options
  • Select an option

  • Save decoda/e47fae916442cea25c78071f2919775b to your computer and use it in GitHub Desktop.

Select an option

Save decoda/e47fae916442cea25c78071f2919775b to your computer and use it in GitHub Desktop.
Erlang Fisher-Yates algorithm
shuffle_list(L) ->
shuffle_list_sub(length(L), L).
shuffle_list_sub(N, L) when N > 1 ->
I = random:uniform(N),
L2 = exchange_element(N, I, L),
shuffle_list_sub(N - 1, L2);
shuffle_list_sub(_N, L) ->
L.
exchange_element(N, N, L) -> L;
exchange_element(N, I, L) ->
A = lists:nth(I, L),
{L1, [H | L2]} = lists:split(N - 1, L),
LA = L1 ++ [A | L2],
{L3, [_ | L4]} = lists:split(I - 1, LA),
L3 ++ [H | L4].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
knuth_yates([]) -> [];
knuth_yates([_] = L) -> L;
knuth_yates(L) -> shuffle_1(L, 1, erlang:length(L)).
shuffle_1(L, Len, Len) -> L;
shuffle_1(L, Cur, Len) ->
S = Cur + erlang:round((Len - Cur) * rand:uniform()),
L2 = swap_element(L, Cur, S),
shuffle_1(L2, Cur + 1, Len).
swap_element(L, N, N) -> L;
swap_element(L, N1, N2) ->
Z = lists:zip(lists:seq(1, length(L)), L),
{value, E1} = lists:keysearch(N1, 1, Z),
{value, E2} = lists:keysearch(N2, 1, Z),
Z2 = lists:keyreplace(N1, 1, lists:keyreplace(N2, 1, Z, E1), E2),
{_, Result} = lists:unzip(Z2),
Result.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment