2010-07-10 5 views
2

Je vais essayer d'être concis cette fois-ci! Je travaille toujours sur Project Euler, cette fois-ci à # 2. Mon vrai problème ici est que je suis terrible avec Ruby. Quand je lance le code suivantErreur de syntaxe dans Ruby, caractère de tuyau inattendu dans un Do

x = 1 
y = 2 
sum = 2 
while x >= 4_000_000 do |x| 

    sum += y if y % 2 == 0 

    z = x + y 

    x = x^y # xor magic 
    y = x^y # xor magic 
    x = x^y # xor magic 

    y = z 
end 

p sum 

Mon interprète lance la sortie suivante:

/Users/Andy/Documents/Programming/Ruby/ProjectEuler/P2.rb:4: syntax error, unexpected '|' 
while x >= 4_000_000 do |x| 
                         ^ 

Je lis why's (Poignant) Guide to Ruby, et je suis assez sûr que j'ai la syntaxe de conduite correcte pour le Do. Quelqu'un pourrait-il souligner ce que je fais mal ici? J'ai essayé de déconner dans beaucoup de façons différentes et je suis à venir short handed

Répondre

6
while (x >= 4_000_000) 
    foo 
end 

Vous n'avez même pas passer x, car il est accessible dans le cadre du bloc englobante.

6

while ne prend pas de bloc. Supprimez la pièce do |x|.

4

while n'est pas une méthode qui prend un bloc, c'est une instruction de bouclage ruby. Il considère la partie entre les while et do (ou nouvelle ligne) comme le test logique et la partie entre le mot de passe do (ou newline) et end comme étant le corps de la boucle.

while x < 10 do x += 1; puts x; end 
while x < 10 
    x += 1 
    puts x 
end 

contraste avec quelque chose comme méthode each du tableau qui prend dans un bloc. Voici la méthode each appelle votre bloc pour chaque élément du tableau (passé dans le bloc comme x)

[1,2,3].each do |x| 
    puts x 
end 

Vous accidentellement combiné les deux, en demandant la boucle while pour appeler votre bloc de code avec le compteur de boucle à transmettre en tant que x. Ce n'est pas comme ça que ça marche ... d'où l'exception d'analyse syntaxique.

2

Quelle question intéressante! Cela m'a également inspiré pour tenter de résoudre le problème. Voici ma solution.

D'abord, certains travaux préparatoires:

class Enumerator 
    def lazy_select 
    Enumerator.new do |y| 
     each do |el| 
     y.yield(el) if yield el 
     end 
    end 
    end 

    alias_method :lazy_find_all, :lazy_select 
end 

module Enumerable 
    def sum 
    reduce(:+) 
    end 
end 

module Math 
    ROOT5 = Math.sqrt(5) 
    PHI = 0.5 + ROOT5/2 

    def self.fibonacci(n) 
    Integer(0.5 + PHI**n/ROOT5) 
    end 
end 

class Integer 
    def fibonacci 
    Math.fibonacci(self) 
    end 
end 

maintenant un Enumerator qui génère une suite infinie de nombres de Fibonacci:

fibs = Enumerator.new do |y| 
    n = -1 
    loop do 
    y.yield (n += 1).fibonacci 
    end 
end 

Et la bonne chose est que nous pouvons maintenant directement exprimer la énoncé du problème original dans le code:

Trouvez la somme de tous les termes pairs de la séquence qui ne dépassent pas quatre millions.

puts fibs.lazy_find_all(&:even?).take_while {|n| n <= 4_000_000 }.sum 

Je pense que cela est un moyen de résoudre beaucoup plus Rubyish le problème. Vous écrivez dans votre question que vous êtes terrible avec Ruby. Mais ce n'est pas vraiment le problème. Le problème réel est que vous êtes bon avec C! En d'autres termes, le vrai problème est que vous n'écrivez pas simplement Ruby, vous écrivez C avec la syntaxe Ruby.

Deux bons exemples sont les suivants:

y % 2 == 0 

et

x = x^y 
y = x^y 
x = x^y 

La façon Ruby d'écrire ces seraient

y.even? 

et

x, y = y, x 
+0

Note: Je * délibérément * n'a pas mis de commentaires ou d'explications dans le code. N'hésitez pas à me poser des questions, mais essayez d'abord de comprendre par vous-même. Je ne serai pas près d'un ordinateur pour les 12 prochaines heures, mais je reviendrai vers vous. –

+0

Aussi, puisque cela ne répond pas vraiment à votre question, je l'ai fait Wiki communautaire afin que je ne gagne pas de réputation. Et comme un avantage secondaire, cela signifie qu'il est beaucoup plus facile pour les autres ou pour vous de l'éditer et d'incorporer des réponses, des questions et des idées. –

+0

Ok, donc je l'ai réduit à x = 1 y = 2 sum = 2 while x < 4_000_000 sum += x if x.even? x, y = y, x+y end p sum Et il donne la réponse incorrecte. Est-ce un problème de syntaxe ou un problème ID10T? – Andy