【问题标题】:C#: N For LoopsC#:N 个 For 循环
【发布时间】:2013-07-01 20:51:42
【问题描述】:

如何将此代码转换为具有 n 个嵌套 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 循环; i 和 j。

这不是家庭作业,我希望反复完成。每个 Console.WriteLine() 都需要像一个元素一样存储在一起。

此程序的输出创建 n 维超空间指数。

【问题讨论】:

  • 你需要让你的函数递归。有一个参数来指定还有多少嵌套循环要运行。当它为零时,做它的“thang”。 :-P 一旦我看到你第一次尝试,我很乐意提供进一步的帮助。 :-)
  • 如果这是家庭作业,请注明,否则,您将通过陈述您的业务案例来帮助自己。
  • 我可以看到很多方法来重写它,以便 num 是一个参数,但是如果不理解这个计算 意味着什么,很难给出代码在哪里的答案清楚地表达了意思。你能描述一下每个元组的确切含义,以及为什么需要它们的序列吗?
  • 每个元组都是 n 维多项式的指数。因此,对于 num=2,程序输出具有 x 个变量的多项式的指数值列表;其中 x 是 for 循环的数量。示例:num = 2, 2 for 循环。我们正在尝试创建一个具有 2 个变量且最大次数为 2 的多项式:x^2*y^0+x^0*y^2+x^1*y^1+x^1*y^0+x ^0*y^1+x^0*y^0 对应上述多项式的输出为:{0 0} {0 1} {0 2} {1 0} {1 1} {2 0}
  • 好的,这很有道理。

标签: c#


【解决方案1】:

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

这是一个方法的草图。填写详细信息留作练习。

首先,我假设您有一个不可变类型“向量”,它可以是 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) 如果不是,下一个向量是什么?

计算下一个向量被赋予当前向量应该非常简单:增加最后一个槽的值。如果这使它太大,请将其设置为零并增加前一个插槽的值。重复直到找到要增加的东西。

有意义吗?

【讨论】:

  • “收益回报”正是我所寻找的。我只是不记得它叫什么,我不知道如何向谷歌描述它。
  • @Ames:为了将来参考,这个概念是迭代器的概念。参看。 msdn.microsoft.com/en-us/library/dscyy5s0.aspx.
【解决方案2】:

通常,对于嵌套循环数在编译时未知的情况,您会使用递归。有以下想法的东西:

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);
    }
}

【讨论】:

  • @mehrdad。他没有使用标准。问题被标记为 c#。 +1 小代码。
  • 需要一些小的语义修改才能与问题中的代码相同,但是 +1。
  • 我想这是一个家庭作业问题。我并不是要写完整的东西,而是想写那样的东西。
【解决方案3】:

相信这不是家庭作业,见下文:

    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());
    }

【讨论】:

    【解决方案4】:

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

    首先考虑一个稍微更一般的情况,您有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 时也是如此,但我懒得去想它马上出去,对不起!)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-29
      • 2021-11-23
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多