Erlang list shuffle

    前一段時間,有同事問Erlang中如何實現將一個列表中元素打亂,我第一反應就是每次根據列表長度隨機出一個下標,將該元素剔出列表,加入到新列表中,重複上面步驟至原列表爲空便可。沒過多久一個同事說,直接給每一個元素一個隨機值,而後排序一下就能夠了。其實遊戲中常常會遇到這種須要打亂順序的狀況,例如洗牌,網上搜尋了一番,發現了些作法。java

參考 http://erlangdisplay.iteye.com/blog/380774 中的算法

版本1(速度快,隨機化很差):數組

shuffle_v1(L) ->
List1 = [{random:uniform(), X} || X <- L],
List2 = lists:keysort(1, List1),
[E || {_, E} <- List2].

上面的版本2 代碼很多,是叫Fisher-Yates shuffle算法,根據http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle中描述,跟我開始想的方法差很少,但原算法涉及到數組的元素交換,我我的感受erlang的list在這方面不太方便,果真有更加簡潔的方案,dom

http://en.literateprograms.org/Fisher-Yates_shuffle_(Erlang) code

shuffle(List) -> shuffle(List, []).

shuffle([], Acc) -> Acc;

shuffle(List, Acc) ->
{Leading, [H | T]} = lists:split(random:uniform(length(List)) - 1, List),
shuffle(Leading ++ T, [H | Acc]).

 固然原算法進行數組的元素交換,只須要一個臨時變量便可完成隨機數組的生成,特別當數組長度很大的狀況下,能節省很多內存。orm

相關文章
相關標籤/搜索