Parte del mio programma mi richiede di essere in grado di mescolare casualmente gli elementi dell'elenco. Ho bisogno di una funzione tale che quando gli do una lista, essa riorganizzerà in modo pseudo-casuale gli elementi nella lista.
Un cambio di accordo È necessario essere visibile ad ogni chiamata con lo stesso elenco.
La mia implementazione sembra funzionare bene ma sento che è piuttosto lunga e sta aumentando la mia base di codice e inoltre, ho la sensazione che non sia la soluzione migliore per farlo. Quindi ho bisogno di un'implementazione molto più breve. Qui è la mia realizzazione:Riproduzione casuale di elementi in un elenco (riordinamento casuale degli elementi di elenco)
-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.
Su eseguirlo in guscio:
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]Sono motivato dal fatto che nel stdlib non c'è tale funzione. Da qualche parte nel mio gioco, ho bisogno di mescolare le cose e ho anche bisogno di trovare la migliore soluzione efficace al problema, non solo quella che funziona.
Qualcuno potrebbe contribuire a creare una versione più breve della soluzione? probabilmente ancora più efficiente? Grazie
Grazie @Adam ottima soluzione. Lo adoro –
ciao. Posso aggiungere che devi seminare prima di usare 'random: uniform'? altrimenti si otterranno gli stessi risultati in diverse esecuzioni della VM e in molte applicazioni questo non è voluto. – user601836
@ user601836 Buon punto! Nota che devi farlo solo una volta per processo, e non per ogni esecuzione di 'shuffle: list/1'. –