Рандомизировать массив PHP с семенем?

Я ищу функцию, через которую я могу передать массив и семя в PHP и получить «рандомизированный» массив. Если бы я снова передал один и тот же массив и одно и то же семя, я бы получил тот же результат.

Я пробовал этот код

 // образец массива
 $ test = array (1,2,3,4,5,6);
 // показать массив
 print_r ($ тест);

 // засеваем генератор случайных чисел
 mt_srand ( '123');
 // генерируем случайное число, основанное на этом
 echo mt_rand ();
 echo "\ n";

 // перетасовывать массив
 перетасовка ($ тест);

 // показать результаты
 print_r ($ тест);

Но, похоже, это не работает. Любые мысли о лучшем способе сделать это?

Этот вопрос танцует вокруг проблемы, но он старый, и никто не дал фактического ответа о том, как это сделать: могу ли я рандомизировать массив, предоставив семя и получив тот же порядок? – "Да, но как?

Обновить

Ответы до сих пор работают с PHP 5.1 и 5.3, но не с 5.2. Просто так, что машина, на которой я хочу запустить эту функцию, использует 5.2.

Может ли кто-нибудь привести пример без использования mt_rand? Он «сломан» в php 5.2, потому что он не будет давать одну и ту же последовательность случайных чисел, основанных на одном семени. См. Страницу php mt_rand и отслеживатель ошибок, чтобы узнать об этой проблеме.

    Вы можете использовать array_multisort для упорядочения значений массива вторым массивом значений mt_rand :

     $arr = array(1,2,3,4,5,6); mt_srand('123'); $order = array_map(create_function('$val', 'return mt_rand();'), range(1, count($arr))); array_multisort($order, $arr); var_dump($arr); 

    Здесь $order – массив значений mt_rand той же длины, что и $arr . array_multisort сортирует значения $order и заказывает элементы $arr соответствии с порядком значений $order .

    Извините, но в соответствии с документацией функция перетасовки автоматически загружается.

    Как правило, вы не должны пытаться придумать свои собственные алгоритмы для рандомизации вещей, поскольку они, скорее всего, будут предвзятыми. Известно, что алгоритм Фишера-Йейса эффективен и беспристрастен:

     function fisherYatesShuffle(&$items, $seed) { @mt_srand($seed); for ($i = count($items) - 1; $i > 0; $i--) { $j = @mt_rand(0, $i); $tmp = $items[$i]; $items[$i] = $items[$j]; $items[$j] = $tmp; } } 

    Пример (PHP 5.5.9):

     php > $original = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); php > $shuffled = (array)$original; php > fisherYatesShuffle($shuffled, 0); php > print_r($shuffled); Array ( [0] => 6 [1] => 0 [2] => 7 [3] => 2 [4] => 9 [5] => 3 [6] => 1 [7] => 8 [8] => 5 [9] => 4 ) php > $shuffled = (array)$original; php > fisherYatesShuffle($shuffled, 0); php > print_r($shuffled); Array ( [0] => 6 [1] => 0 [2] => 7 [3] => 2 [4] => 9 [5] => 3 [6] => 1 [7] => 8 [8] => 5 [9] => 4 ) 

    Проблема в том, что PHP поставляется с двумя генераторами случайных чисел.

    Команда shuffle() не использует генератор случайных чисел mt_rand() ; он использует генератор случайных чисел rand() .

    Поэтому, если вы хотите, чтобы shuffle() использовал последовательность серированных чисел, вам нужно mt_srand() старший рандомизатор, используя srand() а не mt_srand() .

    В большинстве других случаев вы должны использовать mt_rand() а не rand() , так как это лучший генератор случайных чисел.

    Основной вопрос состоит из двух частей. Один из них о том, как перетасовать. Другой – о том, как добавить к нему случайность.

    Простое решение

    Вероятно, это самый простой ответ на главный вопрос. Достаточно для большинства случаев PHP-скриптов. Но не все (см. Ниже).

     function /*array*/ seedShuffle(/*one dimentional array*/ $array, /*integer*/ $seed) { $tmp = array(); for ($rest = $count = count($array);$count>0;$count--) { $seed %= $count; $t = array_splice($array,$seed,1); $tmp[] = $t[0]; $seed = $seed*$seed + $rest; } return $tmp; } 

    Вышеупомянутый метод будет действовать, даже если он не создает настоящие случайные перетасовки для всех возможных комбинаций семенных массивов. Однако, если вы действительно хотите, чтобы он был сбалансированным и все, я думаю, PHP не будет вашим выбором.

    Более полезное решение для продвинутых программистов

    Как заявил Андре Ласло, рандомизация – сложный бизнес. Как правило, лучше всего позволить выделенному объекту обрабатывать его. Я хочу сказать, что вам не нужно беспокоиться о случайности, когда вы пишете функцию тасования. В зависимости от того, какую степень ramdomness вы хотели бы в вашем тасовании, у вас может быть несколько объектов PseudoRandom на выбор. Таким образом, вышесказанное может выглядеть так:

     abstract class PseudoRandom { protected abstract function /*integer*/ nextInt(); public function /*integer*/ randInt(/*integer*/ $limit) { return $this->nextInt()%$limit; } } function /*array*/ seedShuffle($array, /*PseudoRandom Object*/ $rnd) { $tmp = array(); $count = count($array); while($count>0) { $t = array_splice($array,$rnd->randInt($count--),1); $tmp[] = $t[0]; } return $tmp; } 

    Теперь это решение – это то, за что я проголосую. Он отделяет коды тасования от кодов рандомизации. В зависимости от того, какое именно случайное значение вам нужно, вы можете подклассировать PseudoRandom, добавить необходимые методы и ваши предпочтительные формулы. И, поскольку одна и та же функция тасования может использоваться со многими случайными алгоритмами, один случайный алгоритм может использоваться в разных местах.

    В последних версиях PHP mt_rand() функций PHP builtin rand() и mt_rand() не дают вам одинаковых результатов каждый раз. Причина для этого мне не ясна (почему вы хотите, чтобы вы все равно семени, если результат каждый раз отличается.) В любом случае, похоже, единственное решение – написать свою собственную случайную функцию

     class Random { // random seed private static $RSeed = 0; // set seed public static function seed($s = 0) { self::$RSeed = abs(intval($s)) % 9999999 + 1; self::num(); } // generate random number public static function num($min = 0, $max = 9999999) { if (self::$RSeed == 0) self::seed(mt_rand()); self::$RSeed = (self::$RSeed * 125) % 2796203; return self::$RSeed % ($max - $min + 1) + $min; } } 

    Применение:

     // set seed Random::seed(42); // echo 10 numbers between 1 and 100 for ($i = 0; $i < 10; $i++) { echo Random::num(1, 100) . '<br />'; } 

    В приведенном выше коде будет выводиться следующая последовательность при каждом запуске:

     76 86 14 79 73 2 87 43 62 7 

    Просто измените семя, чтобы получить совершенно другую «случайную» последовательность

    Это кажется мне самым легким …

     srand(123); usort($array,function($a,$b){return rand(-1,1);});