【问题标题】:Early termination of recursive iterator block method递归迭代器块方法的提前终止
【发布时间】:2012-12-20 20:01:46
【问题描述】:

我有一个使用递归函数输出数组所有排列的方法:

    /// <summary>
    /// Yields a sequence of all permutations in lexical order
    /// </summary>
    /// <typeparam name="T">Type of item in the input sequence</typeparam>
    /// <param name="input">The initial sequence</param>
    /// <returns>A sequence of all permutations in lexical order</returns>
    public IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> input) 
    {
        var list = input.ToList();
        list.Sort(); // into lexical order

        if (list.Count > 2)
        {
            foreach (var item in list)
            {
                var itemArray = new[] {item};
                T[] otherItems = list.Except(itemArray).ToArray();
                foreach (var permutation in Permute(otherItems))
                    yield return itemArray.Concat(permutation).ToArray();
            }
        }
        else 
        {
            yield return new[] {list[0], list[1]};
            yield return new[] {list[1], list[0]};
        }
    }

但是,当我在 NUnit 测试中运行此函数时,它终止的时间比我认为的要早得多:

    [Test]
    public void Can_print_all_permutations()
    {
        foreach (var p in Permute("123456789"))
        {
            Console.WriteLine(new string(p.ToArray()));
        }
    }

这是测试打印的最后几行(出于发布目的,我用逗号分隔它们):

349527816, 349527861, 349528167, 349528176, 349528617, 3

突然终止让我觉得控制台的缓冲和刷新是问题的一个组成部分,但应该打印的最后一行是 987654321,所以我觉得循环提前终止了。

如果我在循环中包含一个计算,它会更早终止(在 24... 范围内)。

我的实现中有什么东西可以解释这种行为吗?我是在挑战堆栈的极限吗?

【问题讨论】:

  • 控制台输出看起来确实被截断了。您是否尝试将结果写入文件?
  • 您可能在测试运行程序中遇到了限制。
  • 您可以尝试保留一个全局计数器,看看您是否获得了正确数量的排列。
  • 有一个非常好的方法来检查错误,那就是正确地编写测试。而不是转储到控制台而是执行断言,例如您期望的排列数量或特定排列包含在排列列表中。
  • 谢谢,西蒙娜。正是这些技巧让我发现我并没有获得预期的所有结果。

标签: c# recursion nunit yield-return


【解决方案1】:

您使用的测试基础设施很可能具有某种“测试运行的最长时间”限制。枚举所有排列确实需要大量时间。

【讨论】:

  • 我通过编写控制台应用程序尝试了您的想法,该应用程序在大约一秒钟内返回所有 362880 个值。
  • 将我想要执行的计算移到控制台应用程序中会产生我预期的结果,并评估所有排列。这将矛头指向了测试框架。
  • 我用 NUnit 打开了 Bug #1092929。感谢您的帮助!
  • 我下载了 NUnit GUI 测试运行器。测试成功返回了预期数量的值,这让我现在怀疑 ReSharper 的测试运行器。
猜你喜欢
  • 2016-07-21
  • 1970-01-01
  • 2021-12-24
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
  • 2016-04-07
  • 2016-11-10
相关资源
最近更新 更多