2009-04-25 2 views
2

У меня есть этот следующий IEnumerable LINQ запрос:сломать IEnumerable <int> запроса, который использует Enumerable.Range

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; 

Он находит сумму всех чисел, которые могут быть записаны в виде суммы пятых степеней их цифр. Это проект Euler Problem 30

Он отлично работает, как есть. Я знаю, что это nitpick, но диапазон меня раздражает. Я в основном догадался, что нашел правильный результат на уровне 1 000 000, поэтому я позволил ему остановиться. В этом сценарии этого числа было достаточно.

Но это просто жесткое «случайное» число. Если вы посмотрите на код, вы обнаружите, что, как только p == sumofPowers.Sum() будет правдой, вам не нужно больше запускать цикл.

Я знаю yield может делать это в других ситуациях, а break работает в обычных циклах - так что вы можете сделать в этой ситуации?

ответ

4

Вы можете использовать оператор First() для разрыва.

Поскольку LINQ выполняет отложенные вычисления, это будет продолжаться до тех пор, пока вы не достигнете точки, где p == sumofPowers.Sum(), а затем верните первый элемент. Просто заверните весь запрос в (...). First(); для возврата первого значения.

Кроме того, пока вы на нем, нет необходимости конвертировать в строку, а затем в double - вы можете напрямую конвертировать из int -> double и избегать преобразований строк.

+0

Я не уверен, что вы подразумеваете под последней частью. Math.pow (Convert.ToDouble (ch.ToString()), 5) не будет работать, как Math.pow ((двойной) ч, 5) – CasperT

+0

Try: от ч в р пусть sumOfPowers = Math.pow (Convert.ToDouble (ch), 5) –

0

LINQ не является решением всех проблем. У вашей проблемы есть диапазон, который определяется его решением, поэтому с точки зрения «запроса» нет диапазона, что делает его непригодным для известных операций с множеством, таких как LINQ и стандартные методы расширения IEnumerable. Вы бы лучше (и создали более читаемый код), используя инструкцию yield.

1
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(); 
    } 
} 
Смежные вопросы