I have an array of 7 numbers (1,2,3,4,5,6,7) and I want to make pairs of 5 numbers like (1,2,3,4,5),(1,2,3,4,6,),(1,2,3,4,7) .
(1,2,3,4,5) is equal to (4,5,3,1,2)
I would like to know if there is a function in PHP or any algorithm that can do this ?
I have no idea where to start from.
Can you help me ?
I want all the combinations of 7 given numbers ( they are taken from an array ) put into 5 slots,disregarding order
You can use the solution found here http://stereofrog.com/blok/on/070910.
Incase the link goes down here\'s the code....
class Combinations implements Iterator
{
protected $c = null;
protected $s = null;
protected $n = 0;
protected $k = 0;
protected $pos = 0;
function __construct($s, $k) {
if(is_array($s)) {
$this->s = array_values($s);
$this->n = count($this->s);
} else {
$this->s = (string) $s;
$this->n = strlen($this->s);
}
$this->k = $k;
$this->rewind();
}
function key() {
return $this->pos;
}
function current() {
$r = array();
for($i = 0; $i < $this->k; $i++)
$r[] = $this->s[$this->c[$i]];
return is_array($this->s) ? $r : implode(\'\', $r);
}
function next() {
if($this->_next())
$this->pos++;
else
$this->pos = -1;
}
function rewind() {
$this->c = range(0, $this->k);
$this->pos = 0;
}
function valid() {
return $this->pos >= 0;
}
protected function _next() {
$i = $this->k - 1;
while ($i >= 0 && $this->c[$i] == $this->n - $this->k + $i)
$i--;
if($i < 0)
return false;
$this->c[$i]++;
while($i++ < $this->k - 1)
$this->c[$i] = $this->c[$i - 1] + 1;
return true;
}
}
foreach(new Combinations(\"1234567\", 5) as $substring)
echo $substring, \' \';
12345 12346 12347 12356 12357 12367 12456 12457 12467 12567 13456 13457 13467 13567 14567 23456 23457 23467 23567 24567 34567
<?php
echo \"<pre>\";
$test = array(\"test_1\",\"test_2\",\"test_3\");
// Get Combination
$return = uniqueCombination($test);
//Sort
sort($return);
//Pretty Print
print_r(array_map(function($v){ return implode(\",\", $v); }, $return));
function uniqueCombination($in, $minLength = 1, $max = 2000) {
$count = count($in);
$members = pow(2, $count);
$return = array();
for($i = 0; $i < $members; $i ++) {
$b = sprintf(\"%0\" . $count . \"b\", $i);
$out = array();
for($j = 0; $j < $count; $j ++) {
$b{$j} == \'1\' and $out[] = $in[$j];
}
count($out) >= $minLength && count($out) <= $max and $return[] = $out;
}
return $return;
}
?>
output
Array
(
[0] => test_1
[1] => test_2
[2] => test_3
[3] => test_1,test_2
[4] => test_1,test_3
[5] => test_2,test_3
[6] => test_1,test_2,test_3
)
The Math_Combinatorics
in PEAR repository does exactly what you want:
A package that returns all the combinations and permutations, without
repitition, of a given set and subset size. Associative arrays are
preserved.
require_once \'Math/Combinatorics.php\';
$combinatorics = new Math_Combinatorics;
$input = array(1, 2, 3, 4, 5, 6, 7);
$output = $combinatorics->combinations($input, 5); // 5 is the subset size
// 1,2,3,4,5
// 1,2,3,4,6
// 1,2,3,4,7
// 1,2,3,5,6
// 1,2,3,5,7
// 1,2,3,6,7
// 1,2,4,5,6
// 1,2,4,5,7
// 1,2,4,6,7
// 1,2,5,6,7
// 1,3,4,5,6
// 1,3,4,5,7
// 1,3,4,6,7
// 1,3,5,6,7
// 1,4,5,6,7
// 2,3,4,5,6
// 2,3,4,5,7
// 2,3,4,6,7
// 2,3,5,6,7
// 2,4,5,6,7
// 3,4,5,6,7
Here I gave an example how to do so
https://stackoverflow.com/a/8880362/1010916
you should just execute following with the function from the above link:
getCombinations(array(1,2,3,4,5,6,7),5)
Try one of the implementations explained here
Algorithm to return all combinations of k elements from n
Another solution that bases on stack. It\'s quit fast but eats much memory.
Hope that helps someone.
In detail:
function _combine($numbers, $length)
{
$combinations = array();
$stack = array();
// every combinations can be ordered
sort($numbers);
// startup
array_push($stack, array(
\'store\' => array(),
\'options\' => $numbers,
));
while (true) {
// pop a item
$item = array_pop($stack);
// end of stack
if (!$item) {
break;
}
// valid store
if ($length <= count($item[\'store\'])) {
$combinations[] = $item[\'store\'];
continue;
}
// bypass when options are not enough
if (count($item[\'store\']) + count($item[\'options\']) < $length) {
continue;
}
foreach ($item[\'options\'] as $index => $n) {
$newStore = $item[\'store\'];
$newStore[] = $n;
// every combine can be ordered
// so accept only options which is greater than store numbers
$newOptions = array_slice($item[\'options\'], $index + 1);
// push new items
array_push($stack, array(
\'store\' => $newStore,
\'options\' => $newOptions,
));
}
}
return $combinations;
}