-1

Good afternoon guys, I have a following problem of the school to solve, being it in relation to Collatz Problem, where I need to develop an application that will find out the starting number between 1 and 1 million that produces the largest sequence.

I made the following code without applying LINQ, and would like to know how to use linq in this situation.

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 Answers2

0

This is what I'd recommend:

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

Which can be used like this:

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

Running it for a count of 1 000 000 will take some time. But in this case (< 100) the longest sequence is:

97
Igors Sutovs
  • 131
  • 5
  • Wikipedia says the longest sequence should be 524 steps for 837,799. You exceed `int32` when calculating 113383. – NetMage Nov 17 '17 at 19:31
  • @NetMage, true. Do you think Int64 would be enough? – Igors Sutovs Nov 17 '17 at 19:34
  • Yes, long for `n` is enough. Note that your answer doesn't solve the original problem - it doesn't tell the `n` that generates the longest sequence. – NetMage Nov 17 '17 at 19:56
  • 1
    @NetMage, oh yes, I was too quick to read the question. Thought we are looking for the length of the longest sequence, not the number which produces it. Corrected the Linq query and changed the type of n to long. Thanks for the review! – Igors Sutovs Nov 17 '17 at 20:28
  • No problem - really like your new use of `Aggregate`, hope you don't mind I updated my answer to make my extension method based on it. – NetMage Nov 18 '17 at 01:03
0

Create an extension function to find the maximum of a sequence using a function on each element:

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

Create a function to return the Collatz length of a number:

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

Then you can use these and LINQ to computer the answer for a range:

var maxn = Enumerable.Range(2, 1000000-2).Select(n => new { n, Collatz = Collatz(n) }).MaxBy(nc => nc.Collatz).n;
NetMage
  • 26,163
  • 3
  • 34
  • 55