我在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
我无法弄清代码中的问题(我觉得很好)。
答案 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)
你正在重新发明两件事:
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