Часть моей программы требует, чтобы я мог произвольно перемешивать элементы списка. Мне нужна такая функция, чтобы, когда я предоставляю ей список, она псевдослучайно переупорядочивает элементы в списке.
Изменение в расположении Должно быть видимым при каждом вызове с одним и тем же списком. ,
Моя реализация, кажется, работает просто отлично, но я чувствую, что она довольно длинная и увеличивает мою кодовую базу, а также у меня ощущение, что это не лучшее решение для этого. Так что мне нужна гораздо более короткая реализация. Вот моя реализация:
-module(shuffle).
-export([list/1]).
-define(RAND(X),random:uniform(X)).
-define(TUPLE(Y,Z,E),erlang:make_tuple(Y,Z,E)).
list(L)->
Len = length(L),
Nums = lists:seq(1,Len),
tuple_to_list(?TUPLE(Len,[],shuffle(Nums,L,[]))).
shuffle([],_,Buffer)-> Buffer;
shuffle(Nums,[Head|Items],Buffer)->
{Pos,NewNums} = pick_position(Nums),
shuffle(NewNums,Items,[{Pos,Head}|Buffer]).
pick_position([N])-> {N,[]};
pick_position(Nos)->
T = lists:max(Nos),
pick(Nos,T).
pick(From,Max)->
random:seed(begin
(case random:seed(now()) of
undefined ->
NN = element(3,now()),
{?RAND(NN),?RAND(NN),?RAND(NN)};
Any -> Any
end)
end
),
T2 = random:uniform(Max),
case lists:member(T2,From) of
false -> pick(From,Max);
true -> {T2,From -- [T2]}
end.
При запуске в оболочке:
F:\> erl
Eshell V5.8.4 (abort with ^G)
1> c(shuffle).
{ok,shuffle}
2> shuffle:list([a,b,c,d,e]).
[c,b,a,e,d]
3> shuffle:list([a,b,c,d,e]).
[e,c,b,d,a]
4> shuffle:list([a,b,c,d,e]).
[a,b,c,e,d]
5> shuffle:list([a,b,c,d,e]).
[b,c,a,d,e]
6> shuffle:list([a,b,c,d,e]).
[c,e,d,b,a]
Меня мотивирует тот факт, что в
STDLIB такой функции нет. Где-то в моей игре мне нужно все перемешать, а также мне нужно найти лучшее эффективное решение проблемы, а не только то, которое работает.
Может ли кто-нибудь помочь создать более короткую версию решения? наверное еще эффективнее? Спасибо