使用linq c#的Collat​​z序列

时间:2017-11-17 17:50:37

标签: c# linq collatz

大家下午好,我有一个关于学校要解决的问题,因为它与Collat​​z问题相关,我需要开发一个应用程序,它将找出产生最大序列的1到100万之间的起始数字

我在不使用LINQ的情况下制作了以下代码,并且想知道在这种情况下如何使用linq。

var sequence_size = 0;
        var best_number = 0;
        var sequence = 0;


        for (var i = 0; i <= 1000000; i ++)
        {
            var size_ = 1;
            sequence = i;

            while (sequence! = 1)
            {

                sequence = sequence% 2 == 0? sequence / 2: sequence * 3 + 1;
                size ++;
            }

            if (size> size)
            {
                size_sequence = size;
                best_number = i;
            }
        }

2 个答案:

答案 0 :(得分:0)

这是我建议的:

public class MaxSequenceFinder
{
    public int FindBestCollatzSequence(int start, int count)
    {
        return Enumerable.Range(start, count)
            .Select(n => new { Number = n, SequenceLength = CalcCollatzSequence((long)n) })
            .Aggregate((i, j) => i.SequenceLength > j.SequenceLength ? i : j)
            .Number;
    }

    private int CalcCollatzSequence(long n)
    {
        int sequenceLength = 0;

        do
        {
            n = CalcNextTerm(n);
            sequenceLength++;
        }
        while (n != 1);

        return sequenceLength;
    }

    private long CalcNextTerm(long previousTerm)
    {
        return previousTerm % 2 == 0 ? previousTerm / 2 : previousTerm * 3 + 1;
    }
}

可以这样使用:

var finder = new MaxSequenceFinder();
int result = finder.FindBestCollatzSequence(1, 100);
Console.WriteLine(result);

运行计数为1 000 000需要一些时间。但在这种情况下(<100),最长的序列是:

97

答案 1 :(得分:0)

创建一个扩展函数,使用每个元素上的函数找到序列的最大值:

public static class Ext {
    public static T MaxBy<T, TKey>(this IEnumerable<T> src, Func<T, TKey> key, Comparer<TKey> keyComparer = null) {
        keyComparer = keyComparer ?? Comparer<TKey>.Default;
         return src.Aggregate((a,b) => keyComparer.Compare(key(a), key(b)) > 0 ? a : b);
    }
}

创建一个函数以返回数字的Collat​​z长度:

public long Collatz(long seq) {
    long len = 0;

    while (seq != 1) {
        if (seq % 2 == 0) {
            seq /= 2;
            ++len;
        }
        else {
            seq = (3 * seq + 1) / 2;
            len += 2;
        }
    }
    return len;
}

然后你可以使用这些和LINQ来计算范围的答案:

var maxn = Enumerable.Range(2, 1000000-2).Select(n => new { n, Collatz = Collatz(n) }).MaxBy(nc => nc.Collatz).n;