Intereting Posts
Regex для тегов цитат php Как связать параменования с предложением SQL IN () динамически? Проблема NeoClientPHP при извлечении данных из Neo4J Как создать процедуру, которая выполняет аналогичную работу с моей php-функцией (ускорение оптимизации) Ошибка PHP и MySQL. В строке 176 произошла ошибка: объект класса mysqli_result не может быть преобразован в строку jQuery AJAX добавление таблицы tr в конце таблицы который является лучшим способом получить ip Как проверить адресное поле в Codeigniter PHP-CodeIgniter: как получить соответствующие значения строк таблицы html, которые будут удалены с помощью Javascript Преобразование div в загружаемое изображение Файл по умолчанию для Apache localhost Parsing Email Body с 7BIT Content-Transfer-Encoding – PHP Миграция баз данных с помощью механизма отслеживания phpMyAdmin Вариант раскрытия опций PHP Вариант для одного хранимого в БД Вставка базы данных mysql меняет все ID на 4294967295

Генерировать случайный массив с предсказуемым заполнением

ТАК,

Проблема

Это хорошо известно о псевдослучайных числах . «Псевдо» на самом деле означает, что, несмотря на то, что они являются случайными (то есть непредсказуемыми) в целом, они все равно будут одинаковыми в последовательности, в которых использовалось то же самое значение init init. Например, для PHP существует функция mt_srand () . Пример:

mt_srand(1); var_dump(mt_rand(), mt_rand(), mt_rand()); 

Не важно, сколько раз мы запустим наш скрипт: сгенерированные три числа всегда будут одинаковыми в последовательности.

Теперь моя проблема заключается в том, как сделать то же самое – но для перетасовки массива. Т.е. я хочу создать функцию, которая будет принимать входной массив для перетасовки и семени . В пределах одного и того же семенного значения перетасовка должна иметь последовательный одинаковый порядок. Т.е. позвольте нам называть эту функцию shuffleWithSeed() – а затем следующее должно работать для каждого запуска скрипта:

 $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'] //... 

– независимо от того, сколько раз мы будем делать shuffle для нашего массива – я хочу, чтобы следующая последовательность запуска запуска скрипта всегда была одинаковой в пределах одного seed значения.

Мой подход

Я имею в виду этот алгоритм:

  1. Инициализировать генератор случайных чисел с переданным seed
  2. Сгенерируйте N случайных чисел, где N – число элементов $input
  3. Сортировка чисел из шага 2
  4. Сделать соответствующие числа зависят от $input keys.

Я реализовал это в:

 function shuffleWithSeed(array $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 = array_combine(array_keys($random), array_values($input)); ksort($random); return $random; } в function shuffleWithSeed(array $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 = array_combine(array_keys($random), array_values($input)); ksort($random); return $random; } 

– теперь также найден алгоритм Фишера-Йейса – но не уверен, что он может работать с псевдослучайными числами (т. е. с семенем)

Вопрос

Как вы можете видеть, я делаю два вида в своей функции – сначала по значениям, а затем по клавишам.

  • Можно ли это сделать с помощью одного вида? Или совсем нет? Входной массив может быть большим, поэтому я хочу избежать этого.
  • Однако может быть, мой алгоритм не очень хорош? Если да, то какие другие варианты могут быть предложены?

Вот копия и вставка функции, которую я недавно применил для этой цели:

 /** * Shuffles an array in a repeatable manner, if the same $seed is provided. * * @param array &$items The array 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(array &$items, $seed = false) { $items = array_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]) = array($items[$j], $items[$i]); } } 

Он реализует простой перебор Fisher-Yates с генератором случайных чисел.