Ruby项目Euler 35-Circular Primes错误答案

时间:2014-03-28 07:43:20

标签: ruby

我在Ruby中试过Project Euler question 35(我对它很陌生)并得到了错误的答案。

问题:

  

这个数字,197,被称为圆形素数,因为所有的旋转   数字:197,971和719本身就是素数。

     

在100:2,3,5,7,11,13,17,31之下有十三个这样的素数,   37,71,73,79和97。

     

在一百万以下有多少个圆形素数?

我的代码:

require 'prime'

def primes(n)
  nums = [nil, nil, *2..n]
  (2..Math.sqrt(n)).each do |i|
    (i**2..n).step(i) { |m| nums[m] = nil } if nums[i]
  end
  nums.compact
end

prime = primes(1000000)    
circularPrimes = 0

prime.each do |j|
  puts "\n"
  puts j
  flag = false
  j = j.to_s()
  for k in (0..j.length)
    temp = j[k..-1] + j[0..k]
    temp = temp.to_i()
    a = Prime.prime?(temp)
    if a == false then
      flag = true
      break
    end
  end

  if flag == false then
    circularPrimes += 1
  end
end  

puts"\n\n\n\n\n"

puts circularPrimes

我无法弄清代码中的问题(我觉得很好)。

3 个答案:

答案 0 :(得分:1)

我认为你的轮换是1,尝试

j="123456"
j[1..-1] + j[0..1]    # that is k=1 from the above code

产量

"2345612"

这不是一个轮换。可以通过

修复
temp = j[k..-1] + j[0...k]

答案 1 :(得分:1)

正如Patru所说,你的轮换不对。我也不确定你的primes方法,但我没有尝试修复它。因为你不反对使用Prime类,所以我用它来解决一个更容易在眼睛上使用的解决方案,并且据我所知,这是正确的。虽然它看起来表现得非常糟糕,但也许可以进行优化。它将返回1_000_000的答案,但它需要大约70秒才显得非常长。

我想,不应该通过所有数字,我至少应该跳过我已经处理过的所有轮换,并确定是否为圆形素数。无论如何,现在你可以进行一些优化。

require 'prime'

def circular_prime?(n)
  rotations(n).all? { |r| Prime.prime? r }
end

def rotations(n)
  str = n.to_s
  (0...str.length).map do |i|
    (str[i..-1] + str[0...i]).to_i
  end
end

(2 .. 100).select { |n| circular_prime?(n) }
# => [2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, 97]

合并primes方法,您可以将循环素数生成更改为

primes(1_000_000).select { |prime| circular_prime? prime }

该行为等同于您的代码,因为它首先选择高达一百万的所有素数,然后从那里选择循环素数。稍微优化的是从要检查的旋转中移除原始数字,因为我们已经知道它是素数。

我所做的单一计时为这个变体产生了50秒,所以这至少看起来比我原来的快〜(70秒),这并不奇怪,因为我经历了所有数字在2到100万之间的所有轮换,而通过首先选择素数,rotations的输入显着减少。

答案 2 :(得分:0)

你正在重新发明两件事:

  • 生成素数到n(使用Prime.each(n)
  • 旋转数字(使用Array#rotate!

问题可能就在那里。我会这样做:

require 'prime'

def rotations(x)
  digits = x.to_s.chars
  digits.map do
    digits.rotate!.join.to_i
  end
end

circular_primes = Prime.each(1_000_000).select do |p|
  rotations(p).all?{|r| Prime.prime?(r) }
end

puts circular_primes.count