【问题标题】:Generate prime numbers in Ruby (Codewars kata: Primes in numbers)在 Ruby 中生成素数(Codewars kata: Primes in numbers)
【发布时间】:2018-10-24 14:33:00
【问题描述】:

我已经解决了一个 Codewars kata,但我无法提交它,因为我的代码耗时太长。很多人都有这个问题,但我们看不到解决方案。问题是,生成素数需要太长时间(超过 12 秒)(我用一种方法生成素数)。

在我的计算机中,我可以要求 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

【问题讨论】:

  • 我刚刚测试了你的代码 sn-p,它似乎陷入了无限循环(这可能是它在 Codewars 上失败的原因)我刚刚在最后添加了p primeFactors(8),程序得到了永远卡在while 循环中

标签: ruby


【解决方案1】:

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

这是因为如果存在 n = a * b 的因素,那么要么

if a == b == sqrt(n) # 基本上就是sqrt的defn

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

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

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

希望这会有所帮助。

【讨论】:

    【解决方案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 处理器的老机器上。

    【讨论】:

    • 有些人太好了
    猜你喜欢
    • 2023-01-17
    • 1970-01-01
    • 1970-01-01
    • 2020-04-06
    • 1970-01-01
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多