Double linear sequence gives odd results

柔情痞子 提交于 2019-12-11 13:39:31

问题


I'm trying to get my performance skills (none existent) up to par but ran into a problem with writing out a formula into code. This is the formula I'm trying to - quote unquote - "convert" to code.

Consider a sequence u where u is defined as follows:

The number u(0) = 1 is the first one in u. For each x in u, then y = 2 * x + 1 and z = 3 * x + 1 must be in u too. There are no other numbers in u. Ex: u = [1, 3, 4, 7, 9, 10, 13, 15, 19, 21, 22, 27, ...]

1 gives 3 and 4, then 3 gives 7 and 10, 4 gives 9 and 13, then 7 gives 15 and 22 and so on...

And this is what I have so far:

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

The calculations are right until it hits 27. After that it just runs wild and I have no idea what it does wrong.


回答1:


You take one item from sequence and produce two. So You really need some data structure to store them, as their numbers would increase. Heap would be the best. If You want to go with what we have directly in .net, You can use 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);
    }
}

The result:

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...




回答2:


What's going wrong is that you're using a single index to build your values.

When you get to i == 27, as per your example, the first series produces 55 and the second produces 82. But the first should have also produced 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81 before the second produces 82 for your sequence to be properly computed.

You need to run two separate indexes and only increment each when the value produced by their respective series is lowest (or equal to the other).

Here's how I would do it:

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

Now this can be used to produce the entire sequence so it is a good idea to use the LINQ .Take(...) operator.

You could using it like this:

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

...and that gives me:

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

Your test code, once modified to handle the list, works just fine:

    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


来源:https://stackoverflow.com/questions/37516045/double-linear-sequence-gives-odd-results

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!