在两个以上的维度上枚举到无穷大

时间:2014-09-08 19:56:58

标签: c# algorithm loops enumeration

如果我想枚举多个有界值的所有组合,那就很容易了:

for(int i = 0; i <= iMax; i++)
{
    for(int j = 0; j <= jMax; j++)
    {
        for(int k = 0; k <= kMax; k++)
        {
            DoSomething(i,j);
        }
    }
}

同样,如果我想枚举单个无界值,检查某些条件,那也很容易:

BigInteger i = 0;
while(true)
{
    if(Condition(i)) { break; }
    i++;
}

但是如何枚举多个无界值的所有组合呢?对于两个人,我意识到的一种方式是&#34; zig-zag&#34;,就像这样:

BigInteger i = 0;
BigInteger j = 0;
bool direction = true;
while(true)
{
    if(Condition(i,j)) { break; }

    if(direction)
    {
        if(j==0)
        {
            direction = false;
            i++;
        }
        else
        {
            i++;
            j--;
        }
    }
    else
    {
        if(i==0)
        {
            direction = true;
            j++;
        }
        else
        {
            j++;
            i--;
        }
    }
}

这将产生的前几个(ij)对是:(0,0),(1,0),(0,1),(0,2),( 1,1),(2,0),(3,0),(2,1),(1,2)......

所以我的问题是:这个或其他方法如何适应两个以上的维度?例如如果我想循环遍历ijk

注意:我知道有更好的方法来编写这些示例,为了简单起见,我只是尽可能简单地编写它们。

4 个答案:

答案 0 :(得分:2)

for(limit=0;;++limit) {
  for(i0=0; i0<=limit; ++i0) {
    for(i1=0; i1<=limit-i0; ++i1) {
      for(i2=0; i2<=limit-i0-i1, ++i2) {
        for(i3=0; i3<=limit-i0-i1-i2, ++i3) {
          int i4 = limit-i0-i1-i2-i3;
          //do stuff with i0, i1, i2, i3, i4; break when had enough
      }}}}}}

答案 1 :(得分:1)

在2D中:生成所有对(j,k),使得j + k == i,用于增加i。

for (i= 0; true; i++)
  for (j= 0, k= i; 0 <= k; j++, k--)


i=0 -> (0, 0)
i=1 -> (0, 1), (1, 0)
i=2 -> (0, 2), (1, 1), (2, 0)
...

在3D中:生成所有三元组(j,l,m),使得l + m == j用于增加j,j + k = i,用于增加i。

for (i= 0; true; i++)
  for (j= 0, k= i; 0 <= k; j++, k--)
    for (l= 0, m= j; 0 <= m; l++, m--)


i=0, j=0 -> (0, 0, 0)
i=1, j=0 -> (0, 0, 1), (0, 1, 0)
i=1, j=1 -> (1, 0, 1), (1, 1, 0)
i=2, j=0 -> (0, 0, 2), (0, 1, 1), (0, 2, 0)
i=2, j=1 -> (1, 0, 2), (1, 1, 1), (1, 2, 0)
i=2, j=2 -> (2, 0, 2), (2, 1, 1), (2, 2, 0)
...

答案 2 :(得分:0)

因此,正如您所提到的,一个维度很容易。从零开始计算。

两个也不是那么难,只是沿着对角线计算:

11
7    12
4    8    13
2    5    9    14
1    3    6    10    15

对于三个维度,我们可以想象一个金字塔,每次我们都会添加一个新的shell:

在这里,数字将代表该位置的高度,而不是每个项目的添加顺序。

1

1
2    1

1
2    1
3    2    1

您可以将此三维图设想为在球体周围添加贝壳(但移动到离散的,不连续的比例),将二维版本添加为同心圆,将一维版本设置为这些同心圆的半径。当然,在所有情况下,我们只有1/4的图片,因为您将所有内容限制为正值。

那么,我们如何在第n种情况下这样做。

好吧,每个shell由每个维度的每个值组合表示,使得它们的总和是一些常量。首先,您找到每个维度的自然数值的每个组合,使得它们的总和为1,然后您找到总计为2的所有组合,然后您找到所有总和的组合最多3,你继续无限。

答案 3 :(得分:-1)

这确实是一个组合问题,而不是计算机编程问题。

无论如何,你可以这样处理这个无限多变量问题:

At level 0, you have 1 problem to check [0,0,0] At level 1, you have 3 problems to check ([0,0,1],[0,1,0],[1,0,0]) At level 2, you have 6 problems ([0,0,2],[0,2,0],[2,0,0],[0,1,1],[1,0,1],[1,1,0])

所以你必须为每个级别生成所有可能性(递归可以帮助)