その「順列」がどのように呼び出されるかはわかりませんが(おそらく順列ではありません)、セット内の要素が順序付けられているという事実を利用することは有望に見えました(そうでない場合は、インデックスの順序があるため、値の代わりにインデックスを使用します) 右から左にシフトし、すべての左と右の組み合わせを結合します。
これは、再帰またはスタックのいずれかで可能です。私は通常、スタックを好みます。
提案された使用法(関数呼び出しをカプセル化):
$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);
}
}
これが役に立つことを願っています。
別の配列関連のアルゴリズム:モジュラスを使用した並べ替え(参考までに、これを書いているときにその行列のことを思い出しました)