C#:N For循环

时间:2010-01-24 23:18:06

标签: c#

如何将此代码转换为嵌套for循环:

            int num = 4;

            for (int i = 0; i <= num; i++)
            {
                for (int j = 0; j + i <= num; j++)
                {
                    for (int k = 0; i + j + k <= num; k++)
                    {
                        for (int l = 0; i + j + k + l <= num; l++)
                        {
                            Console.WriteLine(i + " " + j + " " + k + " " + l);
                        }
                    }
                }
            }

因此,如果num为2,则只有2个for循环;我和j。

这不是家庭作业,我希望迭代地做。每个Console.WriteLine()都需要像元素一样存储起来。

这个程序的输出创建了n维超夸张指数。

4 个答案:

答案 0 :(得分:14)

好的,你想要一个非递归的解决方案,它在中参数化并且具有一定数量的嵌套循环,是吗?

这是一个执行该操作的方法的草图。填写详细信息仅作为练习。

首先,我假设你有一个不可变类型“Vector”,它可以是0元组,1元组,2元组,3元组,...... n元组。

该方法获取向量的大小并返回该大小的向量序列。

IEnumerable<Vector> MakeVectors(int num)
{
    Vector current = new Vector(num); // make an all-zero vector with num items.
    while(true)
    {
        yield return current;
        Vector next;
        bool gotAnother = GetNextVector(current, out next);
        if (!gotAnother) break;
        current = next;
    }
}

有。问题现在已经减少到两个较小的问题:

1)给定一个大小为num的向量,它是序列中的最后一个向量吗?

2)如果没有,下一个向量是什么?

找出下一个向量给出当前向量的内容应该非常简单:增加最后一个槽的值。如果这样做太大,请将其设置为零并增加上一个插槽的值。重复,直到找到要增加的东西。

有意义吗?

答案 1 :(得分:11)

通常,在具有嵌套循环的场景中使用递归,其中嵌套循环的数量在编译时是未知的。有点想法的东西:

void func(const vector<int> &times, int depth) {
    if (depth == times.size()) return;
    for (int i = 0; i < times[depth]; ++i) {
        cout << depth;
        func(times, depth + 1);
    }
}

答案 2 :(得分:1)

请接受你的说法,这不是家庭作业,见下文:

    public void LoopRecursively(Stack<int> valuesSoFar, int dimensions)
    {
        for (var i = 0; SumOf(valuesSoFar) + i <= dimensions; i++)
        {
            valuesSoFar.Push(i);
            if (valuesSoFar.Count == dimensions)
            {
                Console.WriteLine(StringOf(valuesSoFar));
            }
            else
            {
                LoopRecursively(valuesSoFar, dimensions);
            }
            valuesSoFar.Pop();
        }
    }

    private int SumOf(IEnumerable<int> values)
    {
        return values.Sum(x => x);
    }

    private string StringOf(IEnumerable<int> values)
    {
        return string.Join(" ", values.Reverse().Select(x => x.ToString()).ToArray());
    }

答案 3 :(得分:0)

作为分别操作数字的替代方法,如在递归解决方案和使用Vector&lt;&gt;的操作中所做的那样,您可以依赖于机器表示和算术。如果你需要每次循环检查每个数字,这不会更快,但是如果你实现了迭代器,那么它将减少迭代器中的存储空间,如果你没有使用每一个数值,那么它也可能提高你的效率。无论如何,这是一个有趣的等效方法。这就是......

首先考虑稍微更一般的情况,即你有n嵌套循环,每个循环从0到num计数。在这种情况下,基本上只是从0到num^n - 1计数。所以你可以这样做:

for( int x=0; x<(num^n); x++ )
{
   int digit_0 = x % num;
   int digit_1 = (x/num) % num;
   int digit_2 = (x/num^2) % num;
   // etc.
}

请注意:

  • 如果没有本机整数类型足够大的应用程序,那么您将不得不使用某种大型整数类。这会降低存储和增量部分的效率,但可能不会像使用长度为num的矢量那样多。
  • 如果你真的每次都看一下每个数字,那么你需要一个数字向量,你还没有获得任何东西。当你每次都没有看到所有的数字时,这真的非常有用。
  • 所有除数都应该预先计算,所以你需要保留一个向量!

无论如何,对于您的特定问题,您不希望每次都计入num,您希望计入num - (the sum of the already decided digits)。解决此问题的最简单方法是将适当的continue条件放入循环中。这是在n=2num=10

时替换了一些值
for( x=0; x<100; x++ ) // i.e. x < num*num
{
   int ones = x%10; // i.e. x % num
   int tens = (x/10) % 10; // i.e. (x/num) % num

   if( ones + tens < 10 )
   {
     // actually do work
   }
}

(如果不明显,我并不是说你应该在代码中实际使用100和10,这只是一个说明性的例子。)

您可以通过计算增加x的增量或减小x的范围然后直接映射到子空间而不是整个空间来提高效率。 (但是在2-d和3-d中你只使用了一半的可能值,所以额外的工作只能让你获得2的加速。我认为当n> 3时它是一样的,但是我太懒了现在出来,对不起!)