挑战是找到最小的整数 foo
:
foo % 1..20 == 0
我目前的尝试是蛮力
until foo % 1.upto(20) == 0 do
foo++
end
这会输出错误 unexpected keyword end
。但是,如果我不将 end
关键字放入 irb,代码将永远不会运行,因为该 block 未关闭。
我做了一个空的测试用例,看看我的错误在哪里
until foo % 1.upto(20) == 0 do
end
这会引发一个新错误:无法将枚举数强制转换为固定值
。我想这意味着你不能直接对一个范围执行模数并期望整个范围都有一个整洁的 bool 结果。但我不知道从这里到哪里去。
我的第一次尝试放弃了蛮力,转而尝试更高效/优雅/切题的尝试,具体如下:
foo = 1
1.upto(20) {|bar| foo *= bar unless foo % i == 0}
回答错误。我不明白为什么,但我也很想知道为什么
foo = 1
20.downto(1) {|bar| foo *= bar unless foo % i == 0}
输出不同的答案。
编辑:我本来可以使用 for 循环(我对 ActionScript 中的编程很感兴趣)但它们在 ruby 中的工作方式与我预期的不同。
最佳答案
您的第一个解决方案是错误的,因为 1.upto(20)
是一个 enumerator,也就是说,本质上是一个迭代器,遍历 1 到 20 的值,并且它不能用作模数或与另一个数字进行比较的数字,因为它本身不是数字。
你真的需要两个“循环”:
foo = 1
foo += 1 until (1..20).all? { |i| foo % i == 0 }
第一个循环是until
,然后是all?
。是另一种循环,因为它确保 block ({ |i| foo % i == 0 }
) 对于调用它的范围内的每个元素都是真的 (( 1..20)
)。请注意,我使用的是单行“向后”语法(它也适用于 if
、unless
、while
等)——以上等同于:
foo = 1
until (1..20).all? { |i| foo % i == 0 } do
foo += 1
end
# foo => 232792560
此外,这非常低效,Euler 项目通常涉及比编程更多的数学,非蛮力解决方案可能涉及更多数学但速度要快得多。
关于Ruby:无法将枚举数强制转换为 Fixnum;挣扎于欧拉计划 #5,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10645993/