Я пытаюсь создать массив случайных чисел из 0-n, затем перетасовать (но убедитесь, что ключи и значения НЕ совпадают).
Например:
0 => 3 1 => 2 2 => 4 3 => 0 4 => 1
Обратите внимание, что оба ключа и значения от 0 до 4, но ни один из ключей и значений не меняется.
Есть предположения?
$max = 5; $done = false; while(!$done){ $numbers = range(0, $max); shuffle($numbers); $done = true; foreach($numbers as $key => $val){ if($key == $val){ $done = false; break; } } }
в$max = 5; $done = false; while(!$done){ $numbers = range(0, $max); shuffle($numbers); $done = true; foreach($numbers as $key => $val){ if($key == $val){ $done = false; break; } } }
Еще более короткое решение:
$random_number_array = range(0, 100); shuffle($random_number_array ); $random_number_array = array_slice($random_number_array ,0,10); print_r($random_number_array);
Результат будет:
[0] => 53 [1] => 6 [2] => 16 [3] => 59 [4] => 8 [5] => 18 [6] => 62 [7] => 39 [8] => 22 [9] => 26
Я считаю, что довольно длинное, но также довольно эффективное решение. В отличие от других решений, размещенных здесь, это не может быть deadlock (если не $size<2
), и это не будет делать полный перетасовки каждый раз, когда одно значение не подходит. Вместо этого он заменит это значение другим случайным значением.
function unique_list($size=5) { function all_unique($numbers) { foreach ($numbers as $key=>$value) if ($key==$value) return false; return true; } function flip($a, $b, &$numbers) { $numbers[$a] = $numbers[$a] + $numbers[$b]; $numbers[$b] = $numbers[$a] - $numbers[$b]; $numbers[$a] = $numbers[$a] - $numbers[$b]; } $flip_count = 0; $numbers = range(0,$size-1); shuffle($numbers); while (!all_unique($numbers)) { foreach ($numbers as $key=>$value) { if ($key==$value) { flip($key, rand(0,$size-1), $numbers); $flip_count++; break; } } } printf("Flipped %d values\n", $flip_count); return $numbers; } $list = unique_list(10); print_r($list);
Вышеупомянутое напечатает что-то похожее
Flipped 1 value(s) Array ( [0] => 2 [1] => 5 [2] => 7 [3] => 9 [4] => 6 [5] => 3 [6] => 1 [7] => 8 [8] => 0 [9] => 4 )
Наивное решение:
$n = 10; $rands = array(); for($i=0; $i<$n;$i++) { $ok = false; while(!$ok) { $x=mt_rand(0,$n-1); $ok = !in_array($x, $rands) && $x != $i; } $rands[$i]=$x; } var_dump($rands);
Эффективное решение:
$n = 100; $numbers = range(0, $n-1); $rands = array(); for ($i=0; $i < $n; $i++) { $ok = false; while (!$ok) { $x = array_rand($numbers); $ok = !in_array($numbers[$x], $rands) && $numbers[$x] != $i; } $rands[$i] = $numbers[$x]; unset($numbers[$x]); } var_dump($rands);
не$n = 100; $numbers = range(0, $n-1); $rands = array(); for ($i=0; $i < $n; $i++) { $ok = false; while (!$ok) { $x = array_rand($numbers); $ok = !in_array($numbers[$x], $rands) && $numbers[$x] != $i; } $rands[$i] = $numbers[$x]; unset($numbers[$x]); } var_dump($rands);
изменить: s / rand / mt_rand /
edit # 2: оба решения могут оказаться в тупике, как упоминалось в @AMayer. Я стою исправлено.