I need an efficient algorithm to generate distinct combinations(not allowed to repeat). Each combination has 5 distint numbers(different numbers) that ranges between 1 and 99. The result must be stored in an array. If possible I would like the numbers and range allowed to be customized. The order of number doesn't matter(01 02 03 = 03 01 02)
Ex.:
01 02 03 04 05
02 03 04 05 06
...
Does anyone could help me to build it? I would like to pick up some random combinations from the array. Nowdays I am generating random combinations using mt_rand but It takes too much time, SO SLOW! I believe happens to repeat so often then takes time to generate new one and new one...
I threw this together quickly, seems to work.
<?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";
}
}
Sample output:
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
To Fisher-Yates shuffle the array, see this comment on shuffle for a function you could use in place of shuffle.
Hope that helps.
If you really absolutely need a full set of every possible combination:
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);
Then you can shuffle $allCombinations and extract as many as you want, but you'll need a lot of memory and a lot of time... doing this can never be efficient
Here's the simple code that should run rather fast and do what you describe.
$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));
Note: it only works when you need a few combinations. You don't state that you want all of the possible ones, so I thought if you need just a bunch of them - here's very quick and easy way to do it.
For a bit slower (the more you generate - the slower it goes), but that generates any amount of sets, you can use this code.
$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);
来源:https://stackoverflow.com/questions/9137880/generate-distinct-combinations-php