2009-04-25 7 views
2

Je cette IEnumerable LINQ requête suivante:briser une requête <int> IEnumerable qui utilise 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; 

Il trouve la somme de tous les nombres qui peut être écrit comme la somme des puissances cinquième de leurs chiffres. C'est le projet Euler Problem 30

Cela fonctionne très bien comme il est. Je sais que c'est nitpick, mais la gamme m'ennuie. J'ai essentiellement deviné qu'il a trouvé le bon résultat à 1 000 000, alors je l'ai laissé s'arrêter là. Dans ce scénario, le nombre était suffisant.

Mais c'est juste un nombre "aléatoire" codé en dur. Si vous regardez le code, vous trouvez que dès que p == sumofPowers.Sum() est vrai, vous n'avez plus vraiment besoin de parcourir la boucle.

Je sais que yield peut le faire dans d'autres situations et break fonctionne dans les boucles normales - donc y a-t-il quelque chose que vous pouvez faire dans cette situation?

Répondre

4

Vous pouvez utiliser l'opérateur First() pour sortir. Comme LINQ fait un calcul différé, cela ira jusqu'à ce que vous atteigniez le point où p == sumofPowers.Sum(), puis retourner le premier élément. Juste envelopper la requête entière dans (...). First(); pour retourner la première valeur. De plus, tant que vous y êtes, il n'est pas nécessaire de convertir en une chaîne puis en double - vous pouvez convertir directement depuis int -> double, et éviter les conversions de chaînes.

+0

Je ne suis pas sûr de ce que vous voulez dire par la dernière partie. Math.pow (Convert.ToDouble (ch.ToString()), 5) ne fonctionnera pas car Math.pow ((double) ch, 5) – CasperT

+0

Essayez: de ch en p laisser sumOfPowers = Math.pow (Convert.ToDouble (ch), 5) –

0

LINQ n'est pas la solution à tous les problèmes. Votre problème n'a qu'une plage définie par sa solution, donc, du point de vue de la requête, il n'y a pas de plage, ce qui le rend inadapté aux opérations d'ensemble connues comme LINQ et les méthodes d'extension IEnumerable standard. Vous feriez mieux (et produire un code plus lisible) en utilisant une déclaration de rendement.

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(); 
    } 
} 
Questions connexes