【问题标题】:Compute all possible combinations of a certain number group with no regard to the order计算某个数组的所有可能组合,不考虑顺序
【发布时间】:2013-12-25 03:23:41
【问题描述】:

为此找到一个合适的标题对我来说相当困难。

想象一组数字:

$numbers = array(10, 12, 20, 24, 34, 38, 41, 48);

然后有具体数量的pick:

$picks = 6;

我想做的是生成一个数组,其中包含每个 $picks 数字的组合,但这些数字必须包含在 $numbers 中。

最终的数组结果应包含$numbers 中指定的值的所有可能组合,但顺序并不重要(即意味着 [1,2,3] 等于[1,3,2])。

任何自己编写函数的尝试都失败了,因为我什至不知道我的循环可以基于什么条件。

function computeCombinations(array $numbers, $picks){
    while(?){
    }
    return $results;
}

由于缺乏数学技能,我无法思考如何编写此代码,并且我缺乏该算法的正确命名,无法在网络或 stackoverflow 上搜索它。

函数最终是 javascript 还是 PHP 并不重要。

更新

我已经能够编写一个产生所需结果的函数,但有一个限制:无法真正知道何时找到所有组合。因此我使用了一个相当草率的解决方法 - 一个总迭代计数器,这将使我脱离循环。当然这个功能在实际应用中是不可用的,但是我把它贴出来是为了让读者能够更好地理解我想要实现的目标:

function computeCombinations(array $numbers, $pickCount){

  $results=array();
  $totalIterations=0;

  while(true){
      shuffle($numbers);
      $picks=array_slice($numbers, 0, $pickCount);
      asort($picks);
      $results[implode('',$picks)]=$picks;
      if($totalIterations++ > 10000000)
          break;
  }

  return $results;

}

$out = computeCombinations(array(10, 20, 30, 40, 50, 60, 70, 80), 6);

foreach($out as $v){
    echo implode(', ',$v)."\n";
}

打印:

30, 40, 50, 60, 70, 80
10, 20, 40, 50, 60, 80
20, 30, 40, 50, 60, 80
10, 20, 40, 60, 70, 80
10, 40, 50, 60, 70, 80
20, 30, 50, 60, 70, 80
10, 20, 30, 40, 50, 70
10, 20, 30, 50, 60, 70
20, 30, 40, 60, 70, 80
10, 30, 40, 60, 70, 80
10, 30, 50, 60, 70, 80
10, 20, 30, 50, 60, 80
10, 20, 30, 40, 50, 60
10, 20, 30, 60, 70, 80
10, 30, 40, 50, 60, 70
10, 20, 50, 60, 70, 80
10, 20, 40, 50, 70, 80
10, 20, 30, 50, 70, 80
10, 20, 30, 40, 60, 70
10, 30, 40, 50, 60, 80
20, 30, 40, 50, 60, 70
10, 20, 30, 40, 60, 80
10, 20, 30, 40, 70, 80
20, 30, 40, 50, 70, 80
10, 30, 40, 50, 70, 80
10, 20, 40, 50, 60, 70
20, 40, 50, 60, 70, 80
10, 20, 30, 40, 50, 80

【问题讨论】:

  • 看看我下面的编辑,可能就是你要找的。​​span>
  • 我觉得我对这个问题的描述不是很清楚。
  • 没关系。很高兴您找到了解决方案,干杯。
  • 罗杰。不过谢谢!
  • 不客气 :)

标签: javascript php math combinations combinatorics


【解决方案1】:

这不是一个完美的解决方案,但无论如何:

您可以递归地执行此操作:

版本 2:

function computeCombination(array $source,$picks,$startIndex=0,array $pad=array())
{
    if ($picks<=0) {
        return $pad;
    } elseif ($picks>=count($source)-$startIndex) {
        return array(array_merge($pad,array_slice($source,$startIndex)));
    }
    $result=array();
    foreach (range($startIndex,count($source)-$picks) as $subStartIndex) {
        $subPad=$pad;
        $subPad[]=$source[$subStartIndex];
        if (empty($pad)) {// to make the output look nice 
            $result=array_merge($result,computeCombination($source,$picks-1,$subStartIndex+1,$subPad));
        } else {
            $result=array_merge($result,array(computeCombination($source,$picks-1,$subStartIndex+1,$subPad)));
        }
    }
    return $result;
}
print_r(computeCombination(array(1,2,3,4,5),2));

Online demo

print_r 输出:

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 2
        )

    [1] => Array
        (
            [0] => 1
            [1] => 3
        )

    [2] => Array
        (
            [0] => 1
            [1] => 4
        )

    [3] => Array
        (
            [0] => 1
            [1] => 5
        )

    [4] => Array
        (
            [0] => 2
            [1] => 3
        )

    [5] => Array
        (
            [0] => 2
            [1] => 4
        )

    [6] => Array
        (
            [0] => 2
            [1] => 5
        )

    [7] => Array
        (
            [0] => 3
            [1] => 4
        )

    [8] => Array
        (
            [0] => 3
            [1] => 5
        )

    [9] => Array
        (
            [0] => 4
            [1] => 5
        )

)

(旧版本 1)

function computeCombination(array $source,$picks,$startIndex=0,array $pad=array())
{
    if ($picks<=0) {
        return $pad;
    } elseif ($picks>=count($source)-$startIndex) {
        return array_merge($pad,array_slice($source,$startIndex));
    }
    $result=array();
    foreach (range($startIndex,count($source)-$picks) as $subStartIndex) {
        $subPad=$pad;
        $subPad[]=$source[$subStartIndex];
        $result=array_merge($result,array(computeCombination($source,$picks-1,$subStartIndex+1,$subPad)));
    }
    return $result;
}
print_r(computeCombination(array(1,2,3,4,5),2));

Online demo

【讨论】:

  • 谢谢!这件事似乎有效,尽管在许多情况下它抛出了一个相当深的数组。但它仍然是最好的答案。
【解决方案2】:

编辑

这是另一个更可配置的:

<?php
$TOTAL = 7;
$MAX = 46;
$MIN = 1;

$numbers = array(10, 12, 20, 24, 34, 38, 41, 48);
for($i = 0; $i < $TOTAL; $i++) {
do {
    $new_number = mt_rand($MIN,$MAX);
}
while(in_array($new_number, $numbers));
echo $new_number . "\n";
}
?>

这是另一个:

<?php
// $numbers = range(1, 7);
$numbers = array(10, 12, 20, 24, 34, 38, 41, 48);
shuffle($numbers);
foreach ($numbers as $number) {
    echo "$number ";
}
?>

看看这是否能完成这项工作:

我借用The PHP.net Website - array_rand()的例子

<?php
$input = array(10, 12, 20, 24, 34, 38, 41, 48);

$rand_keys = array_rand($input, 7);
echo $input[$rand_keys[0]] . "\n";
echo $input[$rand_keys[1]] . "\n";
echo $input[$rand_keys[2]] . "\n";
echo $input[$rand_keys[3]] . "\n";
echo $input[$rand_keys[4]] . "\n";
echo $input[$rand_keys[5]] . "\n";
echo $input[$rand_keys[6]] . "\n";
echo $input[$rand_keys[7]] . "\n";
?>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 2021-04-23
    相关资源
    最近更新 更多