Arrays ruby-更快的素数间隙搜索

Arrays ruby-更快的素数间隙搜索,arrays,ruby,numbers,primes,Arrays,Ruby,Numbers,Primes,我正在创建一个方法,gap(g,m,n) 所有3个参数都是整数 gap找到m和n之间的前两个连续素数,它们的差值为g 例如,间隙(2,1,10)=>[3,5] 在从m到n的范围内,1..10, 间隔为2的前两个连续素数是[3,5] 如果相反,它是gap(1,1,10)=>[2,3] 如果它是gap(6,1,10)=>nil 该方法的工作原理是迭代从最小素数2到参数平方根的每个数字,检查参数是否可以被该范围内的任何值均匀整除。如果是,则该方法返回false 所有素数的间隔都是2、4,或者是

我正在创建一个方法,gap(g,m,n)

所有3个参数都是整数


gap找到m和n之间的前两个连续素数,它们的差值为g

例如,间隙(2,1,10)=>[3,5]

在从m到n的范围内,1..10, 间隔为2的前两个连续素数是[3,5]

如果相反,它是gap(1,1,10)=>[2,3]

如果它是gap(6,1,10)=>nil


该方法的工作原理是迭代从最小素数2到参数平方根的每个数字,检查参数是否可以被该范围内的任何值均匀整除。如果是,则该方法返回false


所有素数的间隔都是2、4,或者是由2和4相加而成的数。唯一的例外是2-3的差距

因此,如果给定的间隔参数g是一个类似于3的数字,它既是奇数又大于1,那么该方法会自动返回nil,因为不存在这样的素数间隔


问题 我的问题是这个方法太慢了。通过使用上面的replit链接,您可以获得大约20秒的时间。显然,有可能把它缩短到1秒左右

我尝试过通过过滤掉m..n中已有的偶数进行优化,这很有帮助。但我只是不知道如何才能让这一切进行得更快

我的想法是,在找出m..n中的每一个素数之前,我应该检查每次迭代的间隔是否正确,所以一旦我找到了间隔,我就可以终止该方法,而不看不必要的素数,但我不确定如何实现它


感谢您的帮助,欢迎对我的代码提出任何一般性批评。

请使用Jordan的建议回答:

def gap(g, m, n)

  if g.odd? && g > 1
    return nil
  end

  recent = 0
  current = 0

  (m..n).each do |num|
    if num.odd? && prime?(num)
      current = num  
      if current - recent == g
        break
      else 
        recent = current
      end
    end
  end

  [recent, current] unless current - recent != g

end

gap(2, 10000000, 11000000) 
#=> [10000139, 10000141] 
在3毫秒内完成


谢谢

使用Jordan的建议回答:

def gap(g, m, n)

  if g.odd? && g > 1
    return nil
  end

  recent = 0
  current = 0

  (m..n).each do |num|
    if num.odd? && prime?(num)
      current = num  
      if current - recent == g
        break
      else 
        recent = current
      end
    end
  end

  [recent, current] unless current - recent != g

end

gap(2, 10000000, 11000000) 
#=> [10000139, 10000141] 
在3毫秒内完成


谢谢

您是否尝试分析您的代码?如果不先分析就很难进行优化,但我敢打赌你应该使用一些更快的方法来寻找素数,也许是筛选埃拉托什尼?我不太确定如何完全分析,但我知道代码的瓶颈是这部分素数=(m..n)。选择{num | num.odd?&&prime?(num)}我认为你的想法(“我想的是…”)这将是一个显著的加速。想想如果你是在纸上写出来的,你会怎么做。你可能会在某个地方写下最近的素数和当前的素数,并在进入下一个素数之前检查间隙。你只需要一个循环就可以了。你试过分析你的代码吗?如果不先分析就很难进行优化,但我敢打赌你应该使用一些更快的方法来寻找素数,也许是筛选埃拉托什尼?我不太确定如何完全分析,但我知道代码的瓶颈是这部分素数=(m..n)。选择{num | num.odd?&&prime?(num)}我认为你的想法(“我想的是…”)这将是一个显著的加速。想想如果你是在纸上写出来的,你会怎么做。你可能会在某个地方写下最近的素数和当前的素数,并在进入下一个素数之前检查间隙。你只需要一个循环就可以了。
def gap(g, m, n)

  if g.odd? && g > 1
    return nil
  end

  recent = 0
  current = 0

  (m..n).each do |num|
    if num.odd? && prime?(num)
      current = num  
      if current - recent == g
        break
      else 
        recent = current
      end
    end
  end

  [recent, current] unless current - recent != g

end

gap(2, 10000000, 11000000) 
#=> [10000139, 10000141]