我的程序的一部分要求我能够随机洗牌列表元素。我需要一个函数,当我给它一个列表时,它会伪随机地重新排列列表中的元素。
安排的改变Must每次通话时都可以看到相同的列表。
我的实现似乎工作得很好,但我觉得它相当长,并且正在增加我的代码库,而且,我有一种感觉,这不是执行此操作的最佳解决方案。所以我需要一个更短的实现。这是我的实现:
-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.
在 shell 中运行它:
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]
I am motivated by the fact that in the
STDLIB there is no such function. Somewhere in my game, i need to shuffle things up and also i need to find the best efficient solution to the problem, not just one that works.
Could some one help build a shorter version of the solution ? probably even more efficient ? Thank you