Мне нужен эффективный алгоритм для создания отдельных комбинаций (не разрешается повторять). Каждая комбинация имеет 5 номеров дистрибьютов (разные номера), которые находятся в диапазоне от 1 до 99. Результат должен храниться в массиве. Если возможно, я бы хотел, чтобы номера и диапазон позволяли настраиваться. Порядок номера не имеет значения (01 02 03 = 03 01 02)
Ex.: 01 02 03 04 05 02 03 04 05 06 ...
Кто-нибудь может помочь мне построить его? Я хотел бы получить некоторые случайные комбинации из массива. В настоящее время я генерирую случайные комбинации, используя mt_rand, но это занимает слишком много времени, ТАК МЕДЛЕННО! Я считаю, что случается повторять так часто, а затем требуется время для создания нового и нового …
Я быстро выбросил это вместе, кажется, работает.
<?php $range_low = 1; $range_hi = 99; $num_sets = 10; $set = generateSet($range_low, $range_hi, $num_sets); print_set($set); function generateSet($range_low, $range_hi, $numSets = 5, $numPerSet = 5) { $return = array(); $numbers = array(); for($i = $range_low; $i <= $range_hi; ++$i) { $numbers[] = $i; } for ($s = 0; $s < $numSets; ++$s) { $set = array_values($numbers); shuffle($set); $return[$s] = array(); for ($i = 0; $i < $numPerSet; ++$i) { $val = array_shift($set); $return[$s][] = $val; } } return $return; } function print_set($set) { foreach($set as $subset) { foreach($subset as $value) { echo str_pad($value, 2, '0', STR_PAD_LEFT) . ' '; } echo "\n"; } }
Пример вывода:
90 75 89 43 57 24 54 38 35 10 77 21 55 33 83 37 15 61 09 44 25 31 85 17 20 48 37 45 13 20 82 70 74 64 72 07 24 33 64 45 34 13 39 33 05 13 77 87 70 64
Чтобы Фишер-Йейтс перетасовал массив, см. Этот комментарий в случайном порядке для функции, которую вы могли бы использовать вместо тасования.
Надеюсь, это поможет.
Если вам действительно нужен полный набор всех возможных сочетаний:
function combinations($set,$length) { $combinations = array(); $setCount = count($set); for($i = 0, $n = $setCount; $i <= ($n - $length); $i++) { $combination = array(); $combination[] = $set[$i]; if($length > 1) { $combination = array_merge( $combination, combinations(array_slice($set,1+$i), $length-1) ); } $combinations[] = $combination; } return $combinations; } $allYourNumbers = range(1,99); $allCombinations = combinations($allYourNumbers, 5);
Затем вы можете перетасовать $ allCombinations и извлечь столько, сколько хотите, но вам понадобится много памяти и много времени … это никогда не будет эффективным
Вот простой код, который должен работать довольно быстро и делать то, что вы описываете.
$numbers = range(1, 99); // numbers to pick from $length = 5; // amount of items in the set $sets_amount = 15; // amount of sets you want to generate shuffle($numbers); // randomize function get_set($length, &$numbers) { return array_splice($numbers, 0, $length); } for ($i = 0; $i < $sets_amount; $i++) print_r(get_set($length, $numbers));
Примечание: оно работает только тогда, когда вам нужно несколько комбинаций. Вы не утверждаете, что хотите все возможные, поэтому я подумал, что вам нужно всего лишь кучу их – вот очень быстрый и простой способ сделать это.
Для немного медленнее (чем больше вы генерируете – тем медленнее оно идет), но это генерирует любое количество наборов, вы можете использовать этот код.
$numbers = range(1, 99); // numbers to pick from $length = 5; // amount of items in the set $sets_amount = 200; // amount of sets you want to generate $existing = array(); // where we store existing sets $shuffle_period = count($numbers) - $length - 1; // how often we re-randomize the elements $j = 0; for ($i = 0; $i < $sets_amount; $i++, $j++) { if (!($i % $shuffle_period)) { shuffle($numbers); // randomize at first go and on $shuffle_period $j = 0; } do { $arr = array_slice($numbers, $j, $length); } while (in_array($arr, $existing)); $existing[] = $arr; } print_r($existing);