Ruby Project Euler 35循环素数错误答案

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(

我尝试了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(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)