Ruby Project Euler 35循环素数错误答案
我尝试了Ruby(我对它还很陌生),但得到了错误的答案 问题是: 这个数字197被称为循环素数,因为 数字197971和719本身就是素数 100以下有13个这样的素数:2,3,5,7,11,13,17,31, 37、71、73、79和97 一百万以下有多少个循环素数 我的代码:Ruby Project Euler 35循环素数错误答案,ruby,Ruby,我尝试了Ruby(我对它还很陌生),但得到了错误的答案 问题是: 这个数字197被称为循环素数,因为 数字197971和719本身就是素数 100以下有13个这样的素数: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(
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
我无法从代码中找出问题所在(我认为这很好)。我认为您的旋转已被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]
正如帕特鲁提到的,你的轮换是不对的。我也不确定您的
primes
方法,尽管我没有尝试修复它。因为您不反对使用Prime
类,所以我使用它来解决这个问题,因为它更容易让人看到,而且据我所知是正确的。虽然它的性能似乎很差,但也许可以对其进行优化。它将返回1\u 000\u 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(1_000_000).select { |prime| circular_prime? prime }
该行为相当于您的代码,因为它首先选择最大为一百万的所有素数,然后从中选择循环素数。一个轻微的优化是从要检查的旋转中删除原始的数字,因为我们已经知道它是素数
我做的一次计时为这个变体产生了50秒,所以这至少比我原来的(约70秒)要快,这并不奇怪,因为我经历了200万到100万之间所有数字的所有旋转,然而,通过首先选择素数,
旋转的输入显著减少。您正在重新发明两件事:
- 生成最多n个素数(使用
Prime.each(n)
)
- 旋转数字(使用
数组#旋转!
)
问题可能就在那里的某个地方。我会这样做:
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
旁注:不用自己生成素数,你只需做Prime。每个(1_000_000)
是的,但是答案呢?请描述你当前的输出是什么,以及为什么你认为它是错误的。这仍然不能产生n=100的正确结果。@Cupcake correct,但是k=j.length
首先不应该在那里@Bhavya应该迭代0…j.length
或1…j.length
并相应地调整旋转代码(我的代码将适用于前者)。当k=0
时如何?然后j[0..k-1]
变为j[0..-1]
,结果是字符串加倍而不是旋转。我想你只需要排除运算/数学运算范围的末端,就像这样:j[0…k]
。同样,你是对的。也许从零开始生成所有旋转的整个过程比它应该做的更困难。应该可以将第一个字符旋转到最后一个字符n-1
次(这将使其类似于str=str[1..-1]+str[0]
)。我修正了答案以反映您的输入。不,您从1
而不是0
开始迭代是正确的,这样您就不会生成已生成的旋转,即初始旋转。你也说得对,从头做起很棘手。Ruby实际上有一个rotate
方法,但它只在数组上定义,而不是在字符串上定义:(primes
方法是正确的,我根据Ruby的Prime
序列的结果对它进行了测试。你也可以使用(0…s.length)。映射{I | s.split('').rotate(I.join}< /代码>生成旋转,但你的方法也很简单,所以我会考虑保持它。加速:除了素数2和5,素数不能有任何其他数字比1,3,7,9。所有其他数字出现在数字的末尾,使它非素数。素数相关的技巧,可以更有效地利用这些技巧。@Cupcake是的,你是对的。我也提到过优化(轻微的优化将从要检查的旋转中删除原始数字,因为我们已经知道它是素数),但没有调整旋转
以反映原始代码中的旋转。旋转是以这种方式实现的,因为我的第一个方法需要它,因为它在开始时没有选择100万到100万之间的所有素数,所以它也必须检查初始字符串。但将循环更改为(1…str.length)
对于变量来说,最好先执行素数(1_000_000)
。