这是另一个似乎有效的解决方案。这不是很干净,我知道。但是,嘿!没有递归!;)
<?php
function generate(array $a) {
$multArray = function($mult, $e) {
return $mult * $e;
};
$finalSize = array_reduce($a, $multArray, 1);
$res = array();
$aReverse = array_reverse($a);
for ($i = 0; $i < $finalSize; $i++) {
$tmpReverseRes = array();
foreach ($aReverse as $k => $v) {
$mult = array_reduce(array_slice($aReverse, 0, $k), $multArray, 1);
$tmpReverseRes[] = (int)($i / $mult) % $v;
}
$res[] = join('', array_reverse($tmpReverseRes));
}
return $res;
}
$a = array(2, 3, 3);
print_r(generate($a));
更新:
我们也可以用一个类来实现它:
<?php
class StrangeGenerator {
private $a = null;
private $aReverse = null;
private $combinationsCount = null;
public function __construct(array $array) {
$this->a = $array;
$this->aReverse = array_reverse($array);
$this->combinationsCount = array_reduce($array, 'self::multArray', 1);
}
public function getCombinationFor($index) {
$this->checkRange($index);
$revRes = array();
foreach ($this->aReverse as $k => $v) {
$mult = array_reduce(array_slice($this->aReverse, 0, $k), 'self::multArray', 1);
$revRes[] = (int)($index / $mult) % $v;
}
return join('', array_reverse($revRes));
}
public function getCombinationsCount() {
return $this->combinationsCount;
}
protected function checkRange($index) {
if ($index < 0 || $index >= $this->combinationsCount) {
throw new RangeException('Out of range');
}
}
protected static function multArray($mult, $e) {
return $mult * $e;
}
}
$a = array(2, 3, 3);
$g = new StrangeGenerator($a);
$count = $g->getCombinationsCount();
for ($i = 0; $i < $count; $i++) {
$res = $g->getCombinationFor($i);
echo "$res\n";
}
顺便说一句,此类不会将所有组合保留在内存中。它们是按需计算的。