在Ruby中迭代无限序列

我正在尝试解决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的三角形   除数。   超过五个的第一个三角形的值是多少   一百个除数? 这是我使用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中生成惰性无限序列?     
已邀请:
        在Ruby> = 1.9中,您可以创建一个Enumerator对象,该对象产生所需的任何序列。这是产生无限整数序列的一个:
#!/usr/bin/ruby1.9

sequence = Enumerator.new do |yielder|
  number = 0
  loop do
    number += 1
    yielder.yield number
  end
end

5.times do
  puts sequence.next
end

# => 1
# => 2
# => 3
# => 4
# => 5
要么:
sequence.each do |i|
  puts i
  break if i >= 5
end
编程Ruby 1.9(又名\“ Pickaxe Book \”),第3版。 ed。,p。图83有一个三角数枚举器的例子。修改上面的枚举器以生成三角数应该很容易。我会在这里进行操作,但这将逐字重现示例,可能超出“合理使用”所允许的范围。     
        几个答案很接近,但我实际上看不到有人使用无限范围。 Ruby支持它们就好了。
Inf = Float::INFINITY # Ruby 1.9
Inf = 1.0/0 # Ruby before 1.9
(1..Inf).include?(2305843009213693951)
# => true
(1..Inf).step(7).take(3).inject(&:+)
# => 24.0
就你而言
(2..Inf).find {|i| ((2..( i/2 + 1 )).select{|j| i % j == 0}.count+2)==42 }
=> 2880
您的暴力破解方法很粗糙,可能需要很长时间才能完成。     
        无限是在Float(Ruby 1.9)上定义的
a = Float::INFINITY
puts a #=> Infinity
b = -a
puts a*b #=> -Infinity, just toying

1.upto(a) {|x| break if x >10; puts x}
    
        Ruby的当前版本在很大程度上支持生成器:
sequence = 1.step
    
        在Ruby 2.6中,这变得容易得多:
(1..).each {|n| ... }
资料来源:https://bugs.ruby-lang.org/issues/12912     
        这最好是一个简单的循环。
triangle_number = 1
i  = 1
while num_divisors < 500
  i += 1
  triangle_number += i
  # ...
end
puts i
    
        正如Amadan提到的,您可以使用闭包:
triangle = lambda { t = 0; n = 1; lambda{ t += n; n += 1; t } }[]
10.times { puts triangle[] }
真的不认为它比循环慢得多。您也可以将状态保存在类对象中,但是您将需要进行更多输入:
class Tri
  def initialize
    @t = 0
    @n = 1
  end

  def next
    @t += n
    @n += 1
    @t
  end
end

t = Tri.new
10.times{ puts t.next }
添加: 对于那些喜欢longjmps的人:
require \"generator\"

tri =
  Generator.new do |g|
    t, n = 0, 1
    loop do
      t += n
      n += 1
      g.yield t
    end
  end

puts (0..19).map{ tri.next }.inspect
    
        在Wayne的出色回答的基础上,本着Ruby的精神,用最少的字符数做事是一个稍微更新的版本:
sequence = Enumerator.new { |yielder| 1.step { |num| yielder.yield num } }
显然,它不能解决原始的Euler问题,但对于生成无限的整数序列很有好处。绝对适用于Ruby> 2.0。请享用!     
        在2018年圣诞节那天,Ruby引入了无尽的范围,为解决此问题提供了一种简单的新方法。 这是通过省略范围中的最终字符来实现的,例如:
(1..)
(1...)
(10..)
(Time.now..)
或使用JonasElfström的解决方案进行更新:
(2..).find { |i| ((2..( i / 2 + 1 )).select { |j| i % j == 0 }.count + 2) == 42 }
希望这对某人有用!     
        我相信光纤(我相信在Ruby 1.9中添加了光纤)可能接近您想要的。在这里查看一些信息,或者只是搜索Ruby Fibers     

要回复问题请先登录注册