Parte de mi programa requiere que pueda barajar aleatoriamente los elementos de la lista. Necesito una función tal que cuando le doy una lista, reorganice pseudoaleatoriamente los elementos en la lista.
Un cambio en la disposición Debe ser visible en cada llamada con la misma lista.
Mi implementación parece funcionar bien, pero creo que es bastante larga y está aumentando mi base de códigos y, además, tengo la sensación de que no es la mejor solución para hacerlo. Entonces necesito una implementación mucho más corta. Aquí está mi aplicación:Mezclar elementos en una lista (reorganizar elementos de la lista aleatoriamente)
-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.
En ejecutarlo con cáscara:
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]Estoy motivado por el hecho de que en el stdlib no existe tal función. En algún lugar de mi juego, necesito mezclar las cosas y también necesito encontrar la mejor solución eficiente para el problema, no solo una que funcione.
¿Podría alguien ayudar a construir una versión más corta de la solución? probablemente aún más eficiente? Gracias
Gracias @Adam gran solución. Me encanta –
hola. ¿Puedo agregar que debes sembrar antes de usar 'random: uniform'? de lo contrario, obtendrás los mismos resultados en diferentes ejecuciones de la VM y en muchas aplicaciones esto no es deseado. – user601836
@ user601836 ¡Buen punto! Tenga en cuenta que solo necesita hacer esto una vez por proceso, y no por cada ejecución de 'shuffle: list/1'. –