Часть моей программы требует, чтобы я мог случайным образом перетасовывать элементы списка. Мне нужна функция, так что когда я дам ей список, она будет псевдо-случайным образом переупорядочивать элементы в списке.
Изменение расположения Обязательно должно быть видимым при каждом вызове с тем же список.
Моя реализация, похоже, работает отлично, но я чувствую, что ее довольно долго и увеличивает мою базу кода, а также, я чувствую, что это не лучшее решение для этого. Поэтому мне нужно гораздо более короткое внедрение. Вот моя реализация:
-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 такой функции нет. Где-то в моей игре мне нужно перетасовать вещи, а также мне нужно найти лучшее эффективное решение проблемы, а не только то, что работает. Может ли кто-нибудь помочь построить более короткую версию решения? вероятно, еще более эффективен? Спасибо вам