CasperT
CasperT

Reputation: 3475

break an IEnumerable<int> query which uses Enumerable.Range

I have this following IEnumerable LINQ query:

var query = from p in Enumerable.Range(2, 1000000)
let sumofPowers = from ch in p.ToString()
                  let sumOfPowers = Math.Pow(Convert.ToDouble(ch.ToString()), 5)
                  select sumOfPowers
where p == sumofPowers.Sum()
select p;

It finds the sum of all the numbers that can be written as the sum of fifth powers of their digits. It is the Project Euler Problem 30

It works fine as it is. I know it is nitpick, but the range annoys me. I have basically guessed that it has found the correct result at 1,000,000, so I let it stop there. In this scenario, the number was sufficient.

But it is just a hardcoded "random" number. If you look at the code, you find that as soon as where p == sumofPowers.Sum() is true, you don't really need to run through the loop anymore.

I know yield can do it in under other situations and break works in normal loops - so is there anything you can do in this situation?

Upvotes: 2

Views: 869

Answers (3)

amit
amit

Reputation: 11

class Program
{
    static void Main(string[] args)            
    {
        ulong sum, gh = 0;

        for (ulong i = 2; i <= 355000; i++)
        {
            string s = Convert.ToString(i);
            sum = 0;
            int ddd = s.Length;
            for (int j = 0; j < ddd; j++)
            {
                //sum +=(int)Math.Pow(Convert.ToInt32(s[j]), 4);
                ulong g = Convert.ToUInt64(Convert.ToString(s[j]));
                sum = sum + (ulong)Math.Pow(g, 5);
            }
            // Console.WriteLine(sum);
            if (sum == i)
            {
                gh += i;
            }
        }
        Console.WriteLine(gh);

        Console.ReadKey();
    }
}

Upvotes: 1

Reed Copsey
Reed Copsey

Reputation: 564671

You can use the First() operator to break out.

Since LINQ does deferred calculation, this will go until you reach the point where p == sumofPowers.Sum(), and then return the first element. Just wrap the entire query in (...).First(); to return the first value.

Also, while you're at it, there is no need to convert to a string then to a double - you can convert directly from int -> double, and avoid the string conversions.

Upvotes: 4

Adam Robinson
Adam Robinson

Reputation: 185663

LINQ is not the solution to all problems. Your problem only has a range that is defined by its solution, so from the "query" perspective there IS no range, making this unsuited for known set operations like LINQ and the standard IEnumerable extension methods. You would do better (and produce more readable code) using a yield statement.

Upvotes: 0

Related Questions