仕事で、出くわした仕様でした。
仕様においては、選択肢の最大が5つという事で、5個をサンプルデータとして検証しています。
おそらく、n個でも行けるはずです。
たぶん…
$patern = array( 'A' => 1, 'B' => 2, 'C' => 3, 'D' => 4, 'E' => 5, ); $keys = array_keys( $patern ); print_r( CombinationPattern::getAll( $keys ) ); //CombinationPattern::getAll( $keys ) ; exit; //==================================================================================== class CombinationPattern { function getAll( &$pattern, $flag = false ){ $ret = array(); $max = count( $pattern ); $num = $max; if( $flag ){ for( $n = 1; $n < $num; $n ++ ){ $list = array(); //計算回数最適化 $loop = gmp_intval( gmp_fact($max) ) / ( gmp_intval( gmp_fact($n) ) * gmp_intval( gmp_fact( $max - $n ) ) ); for( $na = 0; $na < $loop; $na ++ ) { $tmp = CombinationPattern::_getOnce( $pattern, $max, $n, $list ); if( $tmp !== false ) $ret[] = $tmp; } } } else { for( $n = $num; $n > 0; $n -- ){ $list = array(); $loop = gmp_intval( gmp_fact($max) ) / ( gmp_intval( gmp_fact($n) ) * gmp_intval( gmp_fact( $max - $n ) ) ); for( $na = 0; $na < $loop; $na ++ ) { $tmp = CombinationPattern::_getOnce( $pattern, $max, $n, $list ); if( $tmp !== false ) $ret[] = $tmp; else echo "false\n"; } } } return $ret; } function _getOnce( &$items, $max, $num, &$duplicate ) { $flag = false; if( $num == 1 ){ $tmp = array(); for( $n = 0; $n < $max; $n ++ ){ $sum = $n + 1; if( !in_array( $sum, $duplicate ) ){ $tmp[] = $items[$n]; $duplicate[] = $sum; return $tmp; } } return false; } for( $n = 0; $n < $max; $n ++ ){ //初期化 $tmp = array(); $line= array(); $sum = 0; $tmp[] = $items[$n]; $line[] = $n; $sum = $n + 1; for( $na = 0; $na < $num -2; $na ++ ) { $idx = $na + ($n + 1); if( $idx >= $max ) $idx -=$max; $tmp[] = $items[$idx]; $line[] = $idx; $sum *= $idx + 1; } $len = count( $line ); $loop = $max - $len; for( $nb = 0; $nb < $loop; $nb ++ ){ $idx = $line[$len-1] + $nb + 1; if( $idx >= $max ) $idx -= $max; $tmp[$len] = $items[$idx]; $swp = $sum * ($idx + 1); //debug //$line[$len] = $idx; //for( $i = 0; $i < count($line); $i ++ ) echo "{$items[$line[$i]]} "; //echo " : {$swp}\n"; if( !in_array( $swp, $duplicate ) ) { $flag = true; $duplicate[] = $swp; break; } } if( $flag ) break; } if( !$flag ) { return false; } return $tmp; } }