在Ruby中生成质数(Codewars kata:质数)

时间:2018-10-24 14:33:00

标签: ruby

我已经解决了Codewars kata指令,但由于我的代码花费的时间太长,因此无法提交。很多人都有这个问题,但是我们看不到解决方案。问题在于,生成质数花费的时间太长(超过12s)(我使用一种方法生成质数)。

在我的计算机上,我可以要求使用Prime类,这可以解决问题。但是在Codewar中,不需要类Prime,因此,我生成质数的方法太慢了。

有帮助吗?

require "pry"

def primeFactors(n)
  start_time = Time.now
  puts start_time
  # find prime numbers smaller than n

  nums = (2..(n-1)).to_a
  odd_nums = nums.select { |num| num.odd? }

  primes = odd_nums.select do |num|
    is_prime(num)
  end

  end_time = Time.now
  duration = end_time - start_time
  puts end_time

  # divide until mod is 1
  dividend = n
  res_primes = []

  while dividend > 1

    primes.each do |prime| # prime divisor
      new_dividend = dividend.to_f / prime
      remainder = dividend % prime
      if remainder.zero?
        dividend = new_dividend
        res_primes << prime
        break
      end
    end
  end

  freqs = {}
  res_primes.each do |res_prime|
    freqs[res_prime] = res_primes.count(res_prime)
  end

  res_string = []
  freqs.keys.each do |key|
    if freqs[key] == 1
      res_string << "(#{key})"
    else
      res_string << "(#{key}**#{freqs[key]})"
    end
  end

  res_string.join
end


def is_prime(n)
  (2..n/2).none?{|i| n % i == 0}
end

2 个答案:

答案 0 :(得分:2)

对于初学者来说,您实际上只需要测试Math.sqrt(n).to_i + 1,这应该有助于获得更大的n值。

这是因为,如果存在一个因子,其中n = a * b,那么要么

如果a == b == sqrt(n)#基本上是sqrt的定义

如果a!= b; a sqrt(n)

如果a和b均小于sqrt(n),则a * b n

其次,这更加复杂,您只需要测试素数到该限制即可。我可以设想一个存储素数的方案。

希望这会有所帮助。

答案 1 :(得分:2)

更高级的选项可能如下所示:

# Is this number a prime?

module PrimeChecker

  @prime_cache = [2,3]

  def self.prime?(n)
    search_limit = Math.sqrt(n).to_i + 1
    last_cache = @prime_cache[-1]

    while last_cache < search_limit do
      last_cache += 2
      @prime_cache << last_cache if PrimeChecker.prime?(last_cache)
    end

    @prime_cache.each do |pn|
      return true if pn > search_limit
      return false if (n % pn) == 0
    end

    true
  end

end

# Sample run
#
# 31 mysh>%=PrimeChecker.prime?(1_000_000_000_000)
# false
# Elapsed execution time = 1.592 seconds.
#

它运行在带有慢速CORE 2 Duo处理器的老式机器上。