欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  php教程

erlang乱序一个List的方案

程序员文章站 2024-01-27 19:58:46
...
最近在系统地看erlang,目前以《erlang programming》为学习材料,看完前面七八章,试图写点东西,发现手足无措,能找到帮助的资料和文档也非常少。

其实我希望有人能一起来学习或讨论。

今日题目: 乱序一个List.

方法一: 一个较为精巧的乱序方案。

[php]

-module(shuffle).

-export([do/1]).

do(L) ->

Len = length(L),

NL = lists:map(fun(X) -> {random:uniform(Len), X} end, L),

NLL = lists:sort(NL),

[ V || {_,V}

其实这个问题挺困扰我的,变量一旦被赋值便不可修改,这个特性让原本写程序的想法和思路完全不同了。我上面的做法是,利用随机数生成一个[{Rand1,Elem1},...,{RandN,ElemN}]这样的列表。

然后再用sort排序后,重新打印出Elem出来,乱序的效果由此达到。

结果大概如下:

[php]

45> c(shuffle).

{ok,shuffle}

46> shuffle:do([1,2,3,4,5]).

[4,5,1,2,3]

47> shuffle:do([1,2,3,4,5]).

[2,1,5,3,4]

48> shuffle:do([1,2,3,4,5]).

[3,1,2,4,5]

49> shuffle:do([1,2,3,4,5]).

[1,5,2,3,4]

50> shuffle:do([1,2,3,4,5]).

[5,1,4,3,2]

51>

方法二:通用洗牌算法

接上文,乱序一个List,我想原有的通用洗牌算法可行的。尝试写了另一个函数。经测试有效,但是我想肯定有优化的空间。代码的风格仍然透露着浓重的过程式思想吧。

%使用洗牌算法的方案

[php]

do2(L) ->

do2(L,[]).

do2([],L) ->

L;

do2(L1,L2) ->

%io:format("L1=~w L2=~w~n",[L1,L2]),

Len = length(L1),

if

Len > 1 ->

NL = lists:split(random:uniform(Len-1), L1),

{[H1|T1],[H2|T2]} = NL,

NL2 = lists:flatten([T1],[H1|T2]),

L11 = lists:append(L2,[H2]),

do2(NL2, L11);

true ->

do2([],lists:append(L2,L1))

end.

其结果为:

128> c(shuffle).

{ok,shuffle}

129> shuffle:do2(lists:seq(0,9)).

[9,2,5,1,8,0,7,3,6,4]

130> shuffle:do2(lists:seq(0,9)).

[8,3,6,5,7,4,9,0,2,1]

131> shuffle:do2(lists:seq(0,9)).

[5,3,7,8,1,9,0,6,2,4]

132> shuffle:do2(lists:seq(0,9)).

[3,0,5,2,1,6,8,4,9,7]

133>

有几点值得思考的,关于这两种方案,是否是真正的洗牌算法。每个数字出现在某个位置是否等概率呢。

还有其它的方法不,欢迎探讨。