ruby-可能的低效算法

ruby-可能的低效算法,ruby,algorithm,Ruby,Algorithm,这是我对一个函数的解决方案,它应该返回两个素数的第一对,如果这些数存在,则在极限m,n之间间隔g,否则为零 这是来自codewars.com的kata,它通过了初步测试。但是,当我提交它时,我收到一条错误消息,说由于我的算法效率低下,它花费了太多的时间(8000ms+) 有人能告诉我到底是什么让代码变慢了,以及应该如何优化它吗 require 'prime' def gap(g, m, n) range = (m..n).to_a primes = [] range.each {

这是我对一个函数的解决方案,它应该返回两个素数的第一对,如果这些数存在,则在极限m,n之间间隔g,否则为零

这是来自codewars.com的kata,它通过了初步测试。但是,当我提交它时,我收到一条错误消息,说由于我的算法效率低下,它花费了太多的时间(8000ms+)

有人能告诉我到底是什么让代码变慢了,以及应该如何优化它吗

require 'prime'

def gap(g, m, n)
  range = (m..n).to_a
  primes = []
  range.each { |num| primes.push(num) if Prime.prime?(num)}


  primes.each_index do |count|
    prv , nxt = primes[count], primes[count+1]
    if !nxt.is_a? Integer
      return nil
    end

    if nxt - prv == g
      return [prv, nxt]
    end
  end
end
试试这个:

require 'prime'

def gap(g, m, n)
  primes = Prime.each(n).select { |p| p >= m }
  primes[0..-2].zip(primes[1..-1]).find { |a, b| b - a == g } 
end

gap(2, 1, 1000)
#=> [3, 5]

gap(6, 1, 1000)
#=> [23, 29]
Prime.each(n).选择{p | p>=m}
返回
m
n
之间所有素数的列表。这比使用
m
n
之间的所有数字构建一个数组,并检查该数组中的每个数字是否为素数具有更好的性能。还值得注意的是,
Prime。每个
都使用埃拉托斯提尼筛算法作为默认值

primes[0..-2].zip(primes[1..-1])
构建每对的数组。这不是迭代
primes
数组中每一对的最有效方法,但我认为它比处理索引读得更好

这可能是另一种选择:

require 'prime'
require 'set'

def gap(g, m, n)
  primes = Set.new(Prime.each(n).select { |p| p>= m })
  primes.each { |prime| return [prime, prime + g] if primes.include?(prime + g) }
end
第二个版本没有构建一个包含所有对的新数组,而是只检查
prime+g
是否也包含在
primes
数组中。我使用a,因为它改进了
include?
O(1)
的查找(而数组上的
include?
将是
O(n)


我不确定哪个版本会更快,运行一些基准测试可能是值得的。第一个版本需要更多的内存,但计算更少。性能可能取决于范围的大小。

谢谢提示。但是,我仍然收到相同的错误消息:进程已终止。如果允许您使用Ruby素数模块,我会在该模块中寻找方法,为您生成范围内的素数,而不是对范围内的所有数字使用素数测试。通常,此类模块的优化程度可能比大多数专业程序员都要好。一个小的优化示例在模块的素数生成器中,re可能越来越复杂,因为您不需要对任何偶数运行素数测试(就像您目前所做的那样)你也可以考虑,有指定间隙的素数必须是连续的吗?你知道该方法所需的三个参数的值不超过8秒吗?请注意,第一个解决方案只会找到由间隙隔开的一对连续素数。例如,对于<代码> g=6 < /代码>,它会找到<代码>。[23,29]
,但不是
[5,11]
。第二个解决方案将两者都找到。你是对的,@Amadan。我错过了优化的这个副作用。我认为如果第二个示例是一个选项,这取决于规范。OP可能必须在他的示例中使用第一个版本。但我会在答案中保留第二个版本,因为它可能会帮助其他人。prematu重新优化是万恶之源——Donald KnuthAs,你说,这取决于任务。根据OP所说,我实际上认为你的第一个版本是错误的:P:D,但实际上,不清楚哪一个是真正的任务。