这次我会尽量简明扼要!我还在使用Project Euler,这次回到#2。我真正的问题是我对Ruby很糟糕。当我运行以下代码时
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
我的翻译推出了以下输出:
/Users/Andy/Documents/Programming/Ruby/ProjectEuler/P2.rb:4: syntax error, unexpected '|'
while x >= 4_000_000 do |x|
^
我正在阅读why's (Poignant) Guide to Ruby,我很确定我的管道语法是正确的。有人能指出我在这里做错了什么吗?我已经尝试过很多不同的方式搞砸了,我很快就出现了。
答案 0 :(得分:6)
while (x >= 4_000_000)
foo
end
您甚至不必传递x
,因为它可以在封闭块的范围内访问。
答案 1 :(得分:6)
while
不会阻止。删除do |x|
部分。
答案 2 :(得分:4)
while
不是一个接受块的方法,它是一个ruby循环语句。它认为while
和do
(或换行符)之间的部分是逻辑测试,而do(或换行符)和end
关键字之间的部分是循环体。< / p>
while x < 10 do x += 1; puts x; end
while x < 10
x += 1
puts x
end
将此与诸如Array的each
方法之类的内容进行对比,该方法包含一个块。这里每个方法为数组的每个元素调用块(作为x传递到块中)
[1,2,3].each do |x|
puts x
end
你不小心将两者组合在一起,要求while循环用循环计数器调用你的代码块作为x传入。这不是如何工作...因此解析异常。
答案 3 :(得分:2)
多么有趣的问题!它激发了我对这个问题的关注。这是我的解决方案。
首先,做一些准备工作:
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
现在Enumerator
生成一个无限的斐波纳契数列:
fibs = Enumerator.new do |y|
n = -1
loop do
y.yield (n += 1).fibonacci
end
end
好消息是我们现在可以直接在代码中表达原始问题陈述:
找出序列中所有偶数值的总和,不超过四百万。
puts fibs.lazy_find_all(&:even?).take_while {|n| n <= 4_000_000 }.sum
我认为这是解决问题的一种更加Ruby的方式。你在问题中写道,你对Ruby很糟糕。但这实际上不是问题所在。 真正的问题是你对C很好!换句话说,真正的问题是你只是不编写Ruby,而是用Ruby语法编写C语言。
两个很好的例子是:
y % 2 == 0
和
x = x ^ y
y = x ^ y
x = x ^ y
Ruby写这些的方法是
y.even?
和
x, y = y, x