在 Ruby 中迭代无限序列
我正在尝试解决 Project Euler 问题 #12:
三角形数序列是通过自然数相加生成的 数字。所以第 7 个三角形数 将为 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. 前十项是:
<预><代码>1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...让我们列出前七个三角形数字的因数:
<前><代码> 1:1 3:1,3 6:1,2,3,6 10: 1,2,5,10 15:1,3,5,15 21: 1,3,7,21 28:1,2,4,7,14,28我们可以看到 28 是第一个超过 5 的三角形数 除数。 第一个大于 5 的三角形数的值是多少 一百因数?
这是我使用 Ruby 提出的解决方案:
triangle_number = 1
(2..9_999_999_999_999_999).each do |i|
triangle_number += i
num_divisors = 2 # 1 and the number divide the number always so we don't iterate over the entire sequence
(2..( i/2 + 1 )).each do |j|
num_divisors += 1 if i % j == 0
end
if num_divisors == 500 then
puts i
break
end
end
我不应该使用像 9_999_999_999_999_999 这样的任意大数字。如果我们有一个像某些函数式语言一样的 Math.INFINITY 序列,那就更好了。如何在 Ruby 中生成惰性无限序列?
I am trying to solve Project Euler problem #12:
The sequence of triangle numbers is generated by adding the natural
numbers. So the 7th triangle number
would be 1 + 2 + 3 + 4 + 5 + 6 + 7 =
28. The first ten terms would be:1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
1: 1 3: 1,3 6: 1,2,3,6 10: 1,2,5,10 15: 1,3,5,15 21: 1,3,7,21 28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five
divisors.
What is the value of the first triangle number to have over five
hundred divisors?
Here's the solution that I came up with using Ruby:
triangle_number = 1
(2..9_999_999_999_999_999).each do |i|
triangle_number += i
num_divisors = 2 # 1 and the number divide the number always so we don't iterate over the entire sequence
(2..( i/2 + 1 )).each do |j|
num_divisors += 1 if i % j == 0
end
if num_divisors == 500 then
puts i
break
end
end
I shouldn't be using an arbitrary huge number like 9_999_999_999_999_999. It would be better if we had a Math.INFINITY sequence like some functional languages. How can I generate a lazy infinite sequence in Ruby?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
有几个答案很接近,但我实际上没有看到有人使用无限范围。 Ruby 很好地支持它们。
在您的情况下,
您的暴力方法很粗糙,并且可能需要很长时间才能完成。
Several answers are close but I don't actually see anyone using infinite ranges. Ruby supports them just fine.
In your case
Your brute force method is crude and can, potentially, take a very long time to finish.
在 Ruby >= 1.9 中,您可以创建一个 Enumerator 对象来生成您喜欢的任何序列。下面是产生无限整数序列的一个:
Or:
Or:
Programming Ruby 1.9< /a>(又名“镐书”),第三。编,页。 83,有一个三角数枚举器的例子。修改上面的枚举器来生成三角数应该很容易。我会在这里这样做,但这会逐字重现示例,可能超出“合理使用”允许的范围。
In Ruby >= 1.9, you can create an Enumerator object that yields whatever sequence you like. Here's one that yields an infinite sequence of integers:
Or:
Or:
Programming Ruby 1.9 (aka "The Pickaxe Book"), 3rd. ed., p. 83, has an example of an Enumerator for triangular numbers. It should be easy to modify the Enumerator above to generate triangular numbers. I'd do it here, but that would reproduce the example verbatim, probably more than "fair use" allows.
Infinity 在 Float 上定义 (Ruby 1.9)
Infinity is defined on Float (Ruby 1.9)
当前版本的 Ruby 大力支持生成器:
Currrent versions of Ruby support generators heavily:
在 Ruby 2.6 中,这变得更加容易:
来源:https://bugs.ruby-lang.org/问题/12912
In Ruby 2.6 this becomes much easier:
Source: https://bugs.ruby-lang.org/issues/12912
这最好作为一个简单的循环。
This would be best as a simple loop.
正如 Amadan 提到的,您可以使用闭包:
不要真的认为它比循环慢得多。您也可以在类对象中保存状态,但您需要更多的输入:
添加:
对于那些喜欢 longjmps 的人:
As Amadan mentioned you can use closures:
Don't really think it is much slower than a loop. You can save state in class object too, but you will need more typing:
Added:
For those who like longjmps:
以 Wayne 的出色答案为基础,并本着用最少字符数做事的 Ruby 精神,这里有一个稍微更新的版本:
显然,它不能解决原始的欧拉问题,但有利于生成无限的整数序列。绝对适用于 Ruby > 2.0。享受!
Building on Wayne's excellent answer and in the Ruby spirit of doing things with the least number of characters here is a slightly updated version:
Obviously, doesn't solve the original Euler problem but is good for generating an infinite sequence of integers. Definitely works for Ruby > 2.0. Enjoy!
2018 年圣诞节,Ruby 引入了 无限范围,为这个问题提供了一种简单的新方法。
这是通过省略范围中的最后一个字符来实现的,例如:
或者使用 Jonas Elfström 的解决方案进行更新:
希望这对某人有用!
On Christmas Day 2018, Ruby introduced the endless range, providing a simple new approach to this problem.
This is implemented by ommitting the final character from the range, for example:
Or to update using Jonas Elfström's solution:
Hope this proves useful to someone!
我相信纤维(我相信是在 Ruby 1.9 中添加的)可能接近你想要的。请参阅此处了解一些信息或者只是搜索红宝石纤维
I believe that fibers (added in Ruby 1.9 I believe) may be close to what you want. See here for some information or just search for Ruby Fibers