erlang - 洗牌列表中的元素(随机重新排列列表元素)

标签 erlang

我的程序的一部分要求我能够随机打乱列表元素。我需要一个函数,当我给它一个列表时,它会伪随机地重新排列列表中的元素。安排变更必须 在每次通话时都可以看到相同的列表。我的实现似乎工作得很好,但我觉得它相当长并且正在增加我的代码库,而且我觉得它不是这样做的最佳解决方案。所以我需要一个更短的实现。这是我的实现:

-模块(随机播放)。
-导出([列表/1])。
-定义(RAND(X),随机:均匀(X))。
-define(TUPLE(Y,Z,E),erlang:make_tuple(Y,Z,E))。

列表(L)->
Len = 长度(L),
数字=列表:seq(1,Len),
tuple_to_list(?TUPLE(Len,[],shuffle(Nums,L,[])))。

洗牌([],_,缓冲区)->缓冲区;
shuffle(Nums,[Head|Items],Buffer)->
{Pos,NewNums} = pick_position(Nums),
洗牌(NewNums,项目,[{Pos,Head}|缓冲区])。

pick_position([N])-> {N,[]};
pick_position(Nos)->
T = 列表:最大(编号),
选择(编号,T)。

选择(从,最大)->
随机:种子(开始
(案例随机:种子(现在())的
未定义->
NN =元素(3,现在()),
{?RAND(NN),?RAND(NN),?RAND(NN)};
任何 -> 任何
结尾)
结尾
),
T2 = 随机:均匀(最大),
案例列表:成员(T2,From)的
假 -> 挑选(从,最大);
真 -> {T2,来自 - [T2]}
结尾。

在 shell 中运行它: F:\> erl
Eshell V5.8.4(使用 ^G 中止)
1> c(随机播放)。
{好的,随机播放}
2> 洗牌:列表([a,b,c,d,e])。
[c,b,a,e,d]
3> 洗牌:列表([a,b,c,d,e])。
[e,c,b,d,a]
4> 洗牌:列表([a,b,c,d,e])。
[a,b,c,e,d]
5> 洗牌:列表([a,b,c,d,e])。
[b,c,a,d,e]
6> 洗牌:列表([a,b,c,d,e])。
[c,e,d,b,a]

我的动机是在 STDLIB 没有这样的功能。在我的游戏中的某个地方,我需要洗牌,而且我需要找到解决问题的最佳有效解决方案,而不仅仅是一个有效的解决方案。
有人可以帮助构建一个较短版本的解决方案吗?可能更有效率?谢谢

最佳答案

1> L = lists:seq(1,10).
[1,2,3,4,5,6,7,8,9,10]

通过创建一个元组列表 {R, X} 将随机数 R 与 L 中的每个元素 X 相关联。对这个列表进行排序并解包元组以得到 L 的打乱版本。
1> [X||{_,X} <- lists:sort([ {random:uniform(), N} || N <- L])].
[1,6,2,10,5,7,9,3,8,4]
2>     

关于erlang - 洗牌列表中的元素(随机重新排列列表元素),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8817171/

相关文章:

二郎哲学: Should I let users deal with wrong input or not?

erlang - 如何在 Mnesia 中定义外键

erlang - 为 mnesia 查询编写查询列表推导式

erlang - 如何确定进程父进程的PID

recursion - Erlang:使用递归从列表中选择唯一项

erlang - Erlang中函数参数列表的可变长度

Erlang 多处理消息接收和发送

Erlang应用程序问题

math - 为什么 erlang 重新定义了像余数这样基本的东西?

erlang - 短路 Erlang 端口映射器守护进程