没有显式枚举器的递归生成器

时间:2017-05-25 04:03:42

标签: c# generator yield-return ienumerator

这是一个使用显式枚举器的生成器:

static IEnumerable<string> generate(string s)
{
    yield return new Regex("e").Replace(s, "", 1);

    yield return new Regex("aaaa").Replace(s, "e", 1);
    yield return new Regex("aa").Replace(s, "bb", 1);
    yield return new Regex("ba").Replace(s, "abbb", 1);

    yield return new Regex("bb").Replace(s, "aa", 1);

    var en0 = generate(new Regex("e").Replace(s, "", 1)).GetEnumerator();
    var en1 = generate(new Regex("aaaa").Replace(s, "e", 1)).GetEnumerator();
    var en2 = generate(new Regex("aa").Replace(s, "bb", 1)).GetEnumerator();
    var en3 = generate(new Regex("ba").Replace(s, "abbb", 1)).GetEnumerator();
    var en4 = generate(new Regex("bb").Replace(s, "aa", 1)).GetEnumerator();

    while(true)
    {
        en0.MoveNext(); yield return en0.Current;
        en1.MoveNext(); yield return en1.Current;
        en2.MoveNext(); yield return en2.Current;
        en3.MoveNext(); yield return en3.Current;
        en4.MoveNext(); yield return en4.Current;
    }
}

this answer中,Eric Lippert建议不要使用枚举器。

如果没有明确的枚举器,是否有一种表达上述内容的好方法?

上面用的发电机是什么?

在Charles C. Pinter的抽象代数书中,练习5.F.3指出:

G 成为{e, a, b, b^2, b^3, ab ab^2, ab^3},其生成符满足a^4 = ea^2 = b^2ba = ab^3。写下 G 表。 ( G 称为四元数组。)

以下计划:

using System;
using System.Collections.Generic;
using System.Linq;

using System.Text.RegularExpressions;

namespace pinter_5.F._1
{
    class Program
    {
        static IEnumerable<string> generate(string s)
        {
            yield return new Regex("e").Replace(s, "", 1);

            yield return new Regex("aaaa").Replace(s, "e", 1);
            yield return new Regex("aa").Replace(s, "bb", 1);
            yield return new Regex("ba").Replace(s, "abbb", 1);

            yield return new Regex("bb").Replace(s, "aa", 1);

            var en0 = generate(new Regex("e").Replace(s, "", 1)).GetEnumerator();
            var en1 = generate(new Regex("aaaa").Replace(s, "e", 1)).GetEnumerator();
            var en2 = generate(new Regex("aa").Replace(s, "bb", 1)).GetEnumerator();
            var en3 = generate(new Regex("ba").Replace(s, "abbb", 1)).GetEnumerator();
            var en4 = generate(new Regex("bb").Replace(s, "aa", 1)).GetEnumerator();

            while(true)
            {
                en0.MoveNext(); yield return en0.Current;
                en1.MoveNext(); yield return en1.Current;
                en2.MoveNext(); yield return en2.Current;
                en3.MoveNext(); yield return en3.Current;
                en4.MoveNext(); yield return en4.Current;
            }
        }

        static void Main(string[] args)
        {
            var G = new List<string>() { "e", "a", "b", "bb", "bbb", "ab", "abb", "abbb" };

            foreach (var x in G)
            {
                foreach (var y in G)
                {
                    var result = generate(x + y).First(elt => G.Contains(elt));

                    Console.Write($"{x,-5} {y,-5} = {result,-5} |");
                }
                Console.WriteLine();
            }
        }
    }
}

显示表格:

enter image description here

2 个答案:

答案 0 :(得分:0)

在上面的评论中,Rob提到一种方法是使用Zip

这是generate使用Zip

的版本
static IEnumerable<string> generate(string s)
{
    yield return new Regex("e").Replace(s, "", 1);

    yield return new Regex("aaaa").Replace(s, "e", 1);
    yield return new Regex("aa").Replace(s, "bb", 1);
    yield return new Regex("ba").Replace(s, "abbb", 1);

    yield return new Regex("bb").Replace(s, "aa", 1);

    var seq =
        generate(new Regex("e").Replace(s, "", 1))
            .Zip(generate(new Regex("aaaa").Replace(s, "e", 1)), (a, b) => new { a = a, b = b }).SelectMany(elt => new[] { elt.a, elt.b })
            .Zip(generate(new Regex("aa").Replace(s, "bb", 1)), (a, b) => new { a = a, b = b }).SelectMany(elt => new[] { elt.a, elt.b })
            .Zip(generate(new Regex("ba").Replace(s, "abbb", 1)), (a, b) => new { a = a, b = b }).SelectMany(elt => new[] { elt.a, elt.b })
            .Zip(generate(new Regex("bb").Replace(s, "aa", 1)), (a, b) => new { a = a, b = b }).SelectMany(elt => new[] { elt.a, elt.b });

    foreach (var elt in seq) yield return elt;
}

答案 1 :(得分:0)

Eric Lippert在上面引用的帖子中包含ZipMany函数。这是使用generate的{​​{1}}版本:

ZipMany