I don’t know what this "permutation" is called (it may not be a permutation), but it was promising for me to use the fact that the elements in the set are ordered (if not, then the order is index, so use the index instead of the value), so to go from right to left and combining all the left with the right combinations.
This is possible with recursion or with the stack, I usually prefer the stack.
Usage as suggested (function call encapsulation):
$funky = function($a, $b) {
printf("(%s) and (%s)\n", implode(',', $a), implode(',', $b));
};
$paired = function($function) {
return function(array $array) use ($function) {
...
};
};
$funkyAll = $paired($funky);
$funkyAll(range(1, 5));
( ) ( ):
(1) and (2,3,4,5) (2,4) and (1,3,5) (1,4,5) and (2,3)
(2) and (1,3,4,5) (2,5) and (1,3,4) (2,3,4) and (1,5)
(3) and (1,2,4,5) (3,4) and (1,2,5) (2,3,5) and (1,4)
(4) and (1,2,3,5) (3,5) and (1,2,4) (2,4,5) and (1,3)
(5) and (1,2,3,4) (4,5) and (1,2,3) (3,4,5) and (1,2)
(1,2) and (3,4,5) (1,2,3) and (4,5) (1,2,3,4) and (5)
(1,3) and (2,4,5) (1,2,4) and (3,5) (1,2,3,5) and (4)
(1,4) and (2,3,5) (1,2,5) and (3,4) (1,2,4,5) and (3)
(1,5) and (2,3,4) (1,3,4) and (2,5) (1,3,4,5) and (2)
(2,3) and (1,4,5) (1,3,5) and (2,4) (2,3,4,5) and (1)
( gist) (array_pop array_shift):
(1) and (2,3,4,5) (2,4) and (1,3,5) (1,4,5) and (2,3)
(2) and (1,3,4,5) (2,5) and (1,3,4) (1,3,4) and (2,5)
(3) and (1,2,4,5) (2,4,5) and (1,3) (1,3,5) and (2,4)
(4) and (1,2,3,5) (2,3,4) and (1,5) (1,3,4,5) and (2)
(5) and (1,2,3,4) (2,3,5) and (1,4) (1,2,3) and (4,5)
(4,5) and (1,2,3) (2,3,4,5) and (1) (1,2,4) and (3,5)
(3,4) and (1,2,5) (1,2) and (3,4,5) (1,2,5) and (3,4)
(3,5) and (1,2,4) (1,3) and (2,4,5) (1,2,4,5) and (3)
(3,4,5) and (1,2) (1,4) and (2,3,5) (1,2,3,4) and (5)
(2,3) and (1,4,5) (1,5) and (2,3,4) (1,2,3,5) and (4)
:
$stack[] = array(array(), $array);
while (list($left, $right) = array_pop($stack)) {
$min = end($left);
foreach ($right as $value)
{
if ($value < $min) continue;
$left2 = array_merge($left, array($value));
$right2 = array_diff($right, $left2);
if (!($left2 && $count = count($right2))) continue;
$function($left2, $right2);
--$count && $stack[] = array($left2, $right2);
}
}
, .
, : ( , )