给出Y数的每个X数组合?

时间:2017-02-11 20:23:40

标签: php arrays math logic mathematical-expressions

我遇到了一个数学问题,因为我无法对逻辑进行编程。

让我用一个例子解释一下:

假设我有4个洞和3个大理石,洞是有序的,我的弹珠是A,B和C,也是有序的。

我需要获得每个可能的ORDERED组合:

ABC4
AB3C
A2BC
1ABC

这很简单,但如果孔的数量发生变化怎么办?我们现在说我有5个洞。

ABC45
AB3C5
A2BC5
1ABC5
AB34C
A2B4C
1AB4C
A23BC
1A3BC
12ABC

现在让我们说我们有5个洞和4个弹珠。

ABCD5
ABC4D
AB3CD
A2BCD
1ABCD

这可以是任意数量的洞和任何数量的大理石。

组合数量由下式给出:

$combinations = factorial($number_of_holes)/(factorial($number_of_marbles)*factorial($number_of_holes-$number_of_marbles)))

(这是你需要它时的阶乘函数)

function factorial($number) { 
    if ($number < 2) { 
        return 1; 
    } else { 
        return ($number * factorial($number-1)); 
    } 
}

我需要什么,无法弄清楚如何编程,是一个函数或循环或其他东西,它返回一个带有孔位置的数组,给定X个孔数和Y个大理石数。

对于第一个示例,它将是:[[4],[3],[2],[1]],第二个:[[4,5],[2,5],[1,5],[3,4],[2,4],[1,5],[2,3],[1,3],[1,2]],第三个:[[5],[4],[3],[2],[1]]

不必按顺序返回,我只需要所有元素。

正如你所看到的,另一种方法是互补或反向或不知道如何调用它,但解决方案是给出Y个孔的X个自由孔的每个组合,所以,如果我有10个孔和5个大理石,将有5个自由孔,返回的阵列将是5个可以形成的每个组合(1,2,3,4,5,6,7,8,9,10),这是252种组合,我需要的是252种组合。

第二种方法的例子:

给定array=[1,2,3,4],返回2和3组的每个组合。

2件套

[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]

3件套

[[1,2,3],[1,2,4],[1,3,4],[2,3,4]]

我需要的是这样做的逻辑,我正在尝试用PHP做,但我无法弄清楚如何做到这一点。

该函数将接收数组和设置大小,并返回集合数组:

function getCombinations($array,$setize){
    //magic code which I can't figure out
    return array(sets);
}

我希望这很清楚,有人可以帮助我,我已经被困了好几天了,但对我来说似乎对我来说太过分了。

这篇文章PHP algorithm to generate all combinations of a specific size from a single set是针对所有可能的组合,重复元素和顺序无关紧要,它是一个很好的领导,我确实读过它,但它没有解决我的问题,它是非常不同的。我需要它们而不重复元素并按照说明进行排序。

假设我的数组中已经有一组[3,4],我不希望[4,3]作为另一组。

1 个答案:

答案 0 :(得分:1)

这是PHP中的递归解决方案:

function getCombinations($array, $setsize){  
    if($setsize == 0)
        return [[]];

    // generate combinations including the first element by generating combinations for 
    // the remainder of the array with one less element and prepending the first element:
    $sets = getCombinations(array_slice($array, 1), $setsize - 1);
    foreach ($sets as &$combo) {
        array_unshift($combo, $array[0]);
    }

    // generate combinations not including the first element and add them to the list:
    if(count($array) > $setsize)
        $sets = array_merge($sets, getCombinations(array_slice($array, 1), $setsize));

    return $sets;
}

// test:
print_r(getCombinations([1, 2, 3, 4], 3));

算法的工作原理如下:

  • 如果setsize为0,则返回单个空组合
  • 否则,生成包含第一个元素的所有组合,通过递归生成数组之外的所有组合,排除第一个元素with setsize - 1个元素,然后将第一个元素添加到每个元素。
  • 然后,如果数组大小大于setsize(意味着包括第一个元素不是必须的),则为列表的其余部分生成所有组合,并将它们添加到我们在第二步中生成的组合。

因此,基本上在每个步骤中,您需要考虑组合中是否包含或排除元素,并将表示两种选择的组合合并在一起。