COSÌ,
Il problema
È ben noto sui numbers pseudo-casuali . "Pseudo" in realtà significa che, nonostante siano casuali (cioè imprevedibili) in generale, saranno uguali in sequenza, in cui è stato utilizzato lo stesso valore di init del generatore. Ad esempio, in PHP c'è la function mt_srand () per farlo. Esempio:
mt_srand(1); var_dump(mt_rand(), mt_rand(), mt_rand());
-non import, quante volte avremo lanciato il nostro script: i tre numbers generati saranno sempre gli stessi in sequenza.
Ora, il mio problema è come fare lo stesso – ma per mischiare l'arrays. Vale a dire, voglio creare una function, che accetterà arrays di input per shuffle e seed . Nello stesso shuffling del valore di seme deve avere lo stesso ordine consecutivo. Cioè, chiamiamo la function shuffleWithSeed()
– e in seguito dovrebbe funzionare per each avvio di script:
$input = ['foo', 'bar', 'baz']; $test = shuffleWithSeed($input, 1000);//1000 is just some constant value var_dump($test); //let it be ['bar', 'foo', 'baz'] $test = shuffleWithSeed($test, 1000); var_dump($test); //let it be ['baz', 'foo', 'bar'] $test = shuffleWithSeed($test, 1000); var_dump($test); //let it be ['baz', 'bar', 'foo'] //...
-e non import quante volte faremo shuffle per il nostro arrays – Voglio che il prossimo ordine di avvio dello script sia sempre lo stesso all'interno di un valore di seed
.
Il mio approccio
Ho in mente questo algorithm:
seed
passato N
numbers casuali, where N
è il numero di $input
membri di $input
$input
tasti di $input
. L'ho implementato in:
function shuffleWithSeed(arrays $input, $seed=null) { if(!isset($seed)) { shuffle($input); return $input; } if(!is_int($seed)) { throw new InvalidArgumentException('Invalid seed value'); } mt_srand($seed); $random = []; foreach($input as $key=>$value) { $random[$key] = mt_rand(); } asort($random); $random = arrays_combine(arrays_keys($random), arrays_values($input)); ksort($random); return $random; }
-ora, abbiamo anche trovato l'algorithm Fisher-Yates – ma non sono sicuro se possa funzionare con numbers pseudocasuali (cioè con seme)
La domanda
Come puoi vedere, sto facendo due tipi nella mia function: prima con i valori e poi con i tasti.
Ecco una copia e incolla di una function che ho implementato qualche tempo fa esattamente per questo scopo:
/** * Shuffles an arrays in a repeatable manner, if the same $seed is provided. * * @param arrays &$items The arrays to be shuffled. * @param integer $seed The result of the shuffle will be the same for the same input ($items and $seed). If not given, uses the current time as seed. * @return void */ protected function seeded_shuffle(arrays &$items, $seed = false) { $items = arrays_values($items); mt_srand($seed ? $seed : time()); for ($i = count($items) - 1; $i > 0; $i--) { $j = mt_rand(0, $i); list($items[$i], $items[$j]) = arrays($items[$j], $items[$i]); } }
Implementa un semplice rimescolamento di Fisher-Yates con un generatore di numbers casuali seminato.