双线性序列给出奇数结果

时间:2016-05-29 23:56:03

标签: c# performance sequence formula

我试图将我的表演技巧(不存在)提升到标准杆,但是在将代码写入代码时遇到了问题。这是我尝试的公式 - 引用unquote - " convert"代码。

  

考虑一个序列u,其中u的定义如下:

     

数字u(0) = 1u中的第一个。   对于x中的每个uy = 2 * x + 1z = 3 * x + 1也必须位于u。   u中没有其他数字。   例如:u = [1, 3, 4, 7, 9, 10, 13, 15, 19, 21, 22, 27, ...]

     

1提供34,然后3提供7104提供9 }和13,然后7提供1522等等......

这就是我到目前为止所做的:

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        Console.WriteLine(DblLinear(10));
        //Expected result: 22
        Console.WriteLine(DblLinear(20));
        //Expected result: 57
        Console.WriteLine(DblLinear(30));
        //Expected result: 91
        Console.WriteLine(DblLinear(50));
        //Expected result: 175
    }
    public static int DblLinear (int n) 
    {
        List<int> linArr = new List<int>();
        linArr.Add(1);

        int i = 0;
        while(linArr.Count < n)
        {
            linArr.Add((2 * linArr[i]) + 1);
            linArr.Add((3 * linArr[i]) + 1);
            linArr.Sort();
            i++;
        }
        return linArr[n - 1];
    }
}

计算是正确的,直到它达到27.然后它只是狂奔,我不知道它做错了什么。

2 个答案:

答案 0 :(得分:5)

你从序列中取出一个项目并产生两个。所以你真的需要一些数据结构来存储它们,因为它们的数量会增加。堆将是最好的。如果您想直接使用.net中的内容,可以使用SortedSet

public static IEnumerable<int> DblLinear2()
{
    SortedSet<int> seq = new SortedSet<int> { 1 };

    while (true)
    {
        int min = seq.First();
        seq.Remove(min);
        yield return min;
        seq.Add(min * 2 + 1);
        seq.Add(min * 3 + 1);
    }
}

结果:

  

1,3,4,7,9,10,13,15,19,21,22,27,28,31,39,40,43,45,46,   55,57,58,63,64,67,79,81,82,85,87 ......

答案 1 :(得分:2)

出现问题的是您使用单个索引来构建您的值。

当你到达i == 27时,根据你的例子,第一个系列产生55,第二个系列产生82。但第一个应该在第二个产生57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81之前生成82,以便正确计算序列。

您需要运行两个单独的索引,并且只有当它们各自系列产生的值最低(或等于另一个)时,才会递增每个索引。

这是我将如何做到的:

public static IEnumerable<int> DblLinear()
{
    Func<int, int> fxy = x => 2 * x + 1;
    Func<int, int> fxz = x => 3 * x + 1;

    var intermediate = new System.Collections.Generic.SortedSet<int>();

    Action<int> safeAdd = x =>
    {
        if (!intermediate.Contains(x))
        {
            intermediate.Add(x);
        }
    };

    safeAdd(1);

    while (true)
    {
        var x = intermediate.First();
        safeAdd(fxy(x));
        safeAdd(fxz(x));
        intermediate.Remove(x);
        yield return x;
    }
}

现在可以使用它来生成整个序列,因此最好使用LINQ .Take(...)运算符。

您可以像这样使用它:

Console.WriteLine(String.Join(", ", DblLinear().Take(20)));

......这让我:

  

1,3,4,7,9,10,13,15,19,21,22,27,28,31,39,40,43,45,46,55

您的测试代码经过修改以处理列表,可以正常工作:

    Console.WriteLine(DblLinear().Skip(10).First());
    //Expected result: 22
    Console.WriteLine(DblLinear().Skip(20).First());
    //Expected result: 57
    Console.WriteLine(DblLinear().Skip(30).First());
    //Expected result: 91
    Console.WriteLine(DblLinear().Skip(50).First());
    //Expected result: 175