Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 素数和_Ruby_Math_Primes - Fatal编程技术网

Ruby 素数和

Ruby 素数和,ruby,math,primes,Ruby,Math,Primes,所以我在HackerRank上做一个编程挑战来帮助我提高技能。(不,这不是面试!我的问题是素数和。(完整描述:)基本上给定一个值n,我要找到所有n位数长的数字,这些数字满足以下三个标准: 每3个连续数字相加为一个素数 每4个连续数字和一个素数 每5个连续数字加一个素数 请参阅链接以获取详细的细分 我有一个基本的函数可以工作,问题是当n变得足够大时,它会崩溃: #!/bin/ruby require 'prime' def isChloePrime?(num) num = num.t

所以我在HackerRank上做一个编程挑战来帮助我提高技能。(不,这不是面试!我的问题是素数和。(完整描述:)基本上给定一个值
n
,我要找到所有n位数长的数字,这些数字满足以下三个标准:

  • 每3个连续数字相加为一个素数
  • 每4个连续数字和一个素数
  • 每5个连续数字加一个素数
请参阅链接以获取详细的细分

我有一个基本的函数可以工作,问题是当
n
变得足够大时,它会崩溃:

#!/bin/ruby
require 'prime'

def isChloePrime?(num)
    num = num.to_s
    num.chars.each_cons(5) do |set|
        return false unless Prime.prime?(set.inject(0) {|sum, i| sum + i.to_i})
    end
    num.chars.each_cons(4) do |set|
        return false unless Prime.prime?(set.inject(0) {|sum, i| sum + i.to_i})
    end
    num.chars.each_cons(3) do |set|
        return false unless Prime.prime?(set.inject(0) {|sum, i| sum + i.to_i})
    end
    return true
end

def primeDigitSums(n)
    total = 0
    (10**(n-1)..(10**n-1)).each do |i| 
       total += 1 if isChloePrime?(i)
    end
    return total
end

puts primeDigitSums(6) # prints 95 as expected
puts primeDigitSums(177779) # runtime error
如果有人能给我指出正确的方向,那就太棒了。不一定要找一个“答案在这里”。理想情况下,他会喜欢“尝试使用这个功能…”

更新以下是第2版:

#!/bin/ruby
require 'prime'

@primes = {}

def isChloePrime?(num)
  num = num.to_s
  (0..num.length-5).each do |i|
    return false unless @primes[num[i,5]]
  end
  return true
end

def primeDigitSums(n)
  total = 0
  (10**(n-1)...(10**n)).each do |i|
    total += 1 if isChloePrime?(i)
  end
  return total
end

(0..99999).each do |val|
    @primes[val.to_s.rjust(5, "0")] = true if [3,4,5].all? { |n| val.digits.each_cons(n).all? { |set| Prime.prime? set.sum } }
end

我认为每一个非负整数都是有效的,如果它的3,4和5位数的每个序列的和形成一个素数

构造相关素数的集合

我们需要确定3位、4位和5位数字的数字之和是否为素数。因此,最大的数字将不大于
5*9
。构造一组素数(一个集合而不是一个数组以加快查找)是很方便的

valid2
是一个散列,它将2位数字(所有有效数字)映射到有效的3位数字数组,该数组通过在2位数字后添加一个数字获得。这些值包括所有有效的3位数字。所有值都是非空数组

valid2 = (10..99).each_with_object({}) do |v2,h|
  p = 10 * v2
  b, a = v2.digits
  h[v2] = (0..9).each_with_object([]) { |c,arr|
    arr << (p+c) if primes.include?(a+b+c) }
end
valid3 = valid2.values.flatten.each_with_object({}) do |v3,h|
  p = 10 * v3
  c, b, a = v3.digits
  h[v3] = (0..9).each_with_object([]) do |d,arr|
    t = b+c+d
    arr << (p+d) if primes.include?(t) && primes.include?(t+a)
  end
end
valid4 = valid3.values.flatten.each_with_object({}) do |v4,h|
  p = 10 * v4
  d, c, b, a = v4.digits
  h[v4] = (0..9).each_with_object([]) do |e,arr|
    t = c+d+e
    arr << ((p+e) % 10_000) if primes.include?(t) &&
      primes.include?(t += b) && primes.include?(t + a)
  end
end
valid4
是一个散列,它将有效的4位数字映射到有效的4位数字数组,该数组通过向键添加数字并删除键的第一位数字来获得。
valid5.values.flatte.size#=>218
是有效的5位数字数组。280个值中有142个是空数组

valid2 = (10..99).each_with_object({}) do |v2,h|
  p = 10 * v2
  b, a = v2.digits
  h[v2] = (0..9).each_with_object([]) { |c,arr|
    arr << (p+c) if primes.include?(a+b+c) }
end
valid3 = valid2.values.flatten.each_with_object({}) do |v3,h|
  p = 10 * v3
  c, b, a = v3.digits
  h[v3] = (0..9).each_with_object([]) do |d,arr|
    t = b+c+d
    arr << (p+d) if primes.include?(t) && primes.include?(t+a)
  end
end
valid4 = valid3.values.flatten.each_with_object({}) do |v4,h|
  p = 10 * v4
  d, c, b, a = v4.digits
  h[v4] = (0..9).each_with_object([]) do |e,arr|
    t = c+d+e
    arr << ((p+e) % 10_000) if primes.include?(t) &&
      primes.include?(t += b) && primes.include?(t + a)
  end
end
转换方法

这是一种方法,用于每次将位数增加1时更新计数

def next_counts(counts)
  counts.each_with_object({}) do |(k,v),new_valid|
    @transition[k].each do |new_v|
      (new_valid[new_v] = new_valid[new_v].to_i + v) if @transition.key?(k)
    end
  end
end
prime\u digital\u sum
方法

def prime_digit_sum(n)
  case n
  when 1 then 10
  when 2 then 90
  when 3 then @transition.sum { |k,v| (10..99).cover?(k) ? v.size : 0 }
  else
    counts = @transition.select { |k,_| (100..999).cover?(k) }.
                         values.flatten.product([1]).to_h   
    (n - 4).times { counts = next_counts(counts) }
    counts.values.sum % (10**9 + 7)
  end
end
请注意,对于
n=4
,哈希
计数
的键是有效的4位数字,值都等于
1

counts = @transition.select { |k,_| (100..999).cover?(k) }.
  values.flatten.product([1]).to_h   
  #=> {1011=>1, 1020=>1, 1101=>1, 1110=>1, 1200=>1, 2003=>1, 2005=>1,
  #    ...
  #    8902=>1, 8920=>1, 8968=>1, 9020=>1, 9110=>1, 9200=>1}

counts.size
  #=> 280
如图所示,对于
n>=5
,每当
n
增加1时,
计数就会更新。值之和等于有效的
n位
数字的数量

每个有效
n
-位数字的最后四位数字构成的数字是
count
的键之一。每个键的值是一个数字数组,其中包含通过向键添加数字生成的所有有效
(n+1)
-位数字的最后四位数字

例如,考虑
n=6
counts
值,该值如下所示

counts
  #=> {1101=>1, 2003=>4, 2005=>4, 300=>1, 302=>1, 304=>1, 308=>1, 320=>1,
  #    322=>1, 326=>1, 328=>1, 380=>1, 382=>1, 386=>1, 388=>1, 500=>1,
  #    502=>1, 506=>1, 508=>1, 560=>1, 562=>1, 566=>1, 568=>1, 1200=>7,
  #    3002=>9, 3020=>4, 3200=>6, 5002=>6, 9200=>4, 200=>9, 1020=>3, 20=>3,
  #    5200=>4, 201=>2, 203=>2, 205=>2, 209=>2, 5020=>2, 9020=>1}
考虑键
2005
,并注意

@transition[2005]
  #=> [50, 56]
我们看到有
4
有效的6位数字,其最后4位是
2005
,并且对于这些
4
数字中的每一个,通过添加数字
0
6
生成一个有效数字,从而生成最后5位是
20050
20056
的数字。然而,我们需要继续请保留最后四位数字,
0050
0056
,它们是数字
50
56
。因此,当为
n=7
重新计算
计数时——称之为
counts7
——我们将
4
添加到
counts7[50]
counts7[56]
计数的其他键
k
(对于
n=6
)可能是这样的,
@transition[k]
的值包括
50
56
,因此它们也将有助于
计数7[50]
计数7[50]

选择性结果

让我们对
n

puts "digits  nbr valid*  seconds"
[1, 2, 3, 4, 5, 6, 20, 50, 100, 1_000, 10_000, 40_000].each do |n|
  print "%6d" % n
  t = Time.now
  print "%11d" % prime_digit_sum(n)
  puts "%10f" % (Time.now-t).round(4)
end
puts "\n* modulo (10^9+7)"

digits  nbr valid*  seconds
     1         10  0.000000
     2         90  0.000000
     3        303  0.000200
     4        280  0.002200
     5        218  0.000400
     6         95  0.000400
    20      18044  0.000800
    50  215420656  0.001400
   100  518502061  0.002700
  1000  853799949  0.046100
 10000  590948890  0.474200
 40000  776929051  2.531600

我将通过预先计算所有允许的5位子序列的列表来解决这个问题:“00002”失败,而“28300”是允许的,等等。这可能被设置为二进制数组或哈希集


一旦你有了这个列表,你就可以通过一次在第一个步骤上移动一个5位数的帧来检查任何数字。

如果你设置了一个调试点,也许你可以找出哪一行代码触发了运行时……也许这个特定的数字会在你的某些行中引起一些数学问题这只是一个提示,但会比conv好得多插入一个字符串并拆分为“char”数组,然后将这些“char”转换回整数。Ruby的一个约定(几乎所有Ruby程序员都采用)是用于变量和方法的名称(例如,
is_chloe_prime?
)@ForeverZer0,我在玩其中的一些…
整数#数字
对于
10**177778
(断开的第一个数字)需要整整一分钟的时间如果您使用
to_.s.chars
@simpletime,这几乎是即时的,但在这种情况下
to_.s.chars
肯定是一种方法。另一种情况是,大整数会破坏Ruby。对于大数,在
prime.rb
的其他方法中也会发生同样的情况。在查看源代码时,它可能会提交错误报告在大数情况下,is的表现应该与预期的一样,但事实并非如此。令人难以置信的详细和有用的响应!!谢谢!重读这篇文章,你在第二段中让我有点不知所措。整个问题是,当n大于10(或至少超时)时,函数会失败即使构建散列也会失败…这又是一个令人惊讶的详细响应,不幸的是它不起作用…我知道事实上有95个六位数满足要求,这个解决方案给了我一个完全不同的答案。扎克,我还在努力