Reputation: 2410
As the title says. I want to find all left truncatable primes between 10 and 9999 using Ruby language. Following is what I tried and it gives me the result.
require 'prime'
require 'benchmark'
trunc_primes = []
Benchmark.bmbm do |bm|
bm.report{
Prime.each(10000).each do |num|
is_tunc_prime = true
(1..(num.to_s.length)).to_a.reverse.each do |i|
factor = 10 ** i
unless num.divmod(factor)[1].prime?
is_tunc_prime = false
break
end
end
trunc_primes << num if is_tunc_prime
end;nil
}
end
Question: Can this script be optimized further(lesser loops, use formula rather than factor division technique) ?
Benchmark stats:
➜ truncatable git:(master) ✗ ruby truncatable_primes.rb
Rehearsal ------------------------------------
0.000000 0.000000 0.000000 ( 0.000026)
--------------------------- total: 0.000000sec
user system total real
0.000000 0.000000 0.000000 ( 0.000020)
➜ truncatable git:(master) ✗ ruby truncatable_primes.rb
Rehearsal ------------------------------------
0.000000 0.000000 0.000000 ( 0.000024)
--------------------------- total: 0.000000sec
user system total real
0.000000 0.000000 0.000000 ( 0.000017)
➜ truncatable git:(master) ✗ ruby truncatable_primes.rb
Rehearsal ------------------------------------
0.000000 0.000000 0.000000 ( 0.000028)
--------------------------- total: 0.000000sec
user system total real
0.000000 0.000000 0.000000 ( 0.000044)
➜ truncatable git:(master) ✗ ruby truncatable_primes.rb
Rehearsal ------------------------------------
0.000000 0.000000 0.000000 ( 0.000030)
--------------------------- total: 0.000000sec
user system total real
0.000000 0.000000 0.000000 ( 0.000019)
Benchmark above script and Amadan's script
Rehearsal ------------------------------------------
mine 0.020000 0.000000 0.020000 ( 0.022804)
Amadan 0.000000 0.000000 0.000000 ( 0.001559)
--------------------------------- total: 0.020000sec
user system total real
mine 0.020000 0.000000 0.020000 ( 0.019625)
Amadan 0.000000 0.000000 0.000000 ( 0.001540)
Upvotes: 3
Views: 102
Reputation: 198418
Since you're already using Prime
, why invent hot water?
Prime.each(10000).reject { |p| p < 10 }.select { |p|
s = p.to_s
1.upto(s.length - 1).all? { |i|
s[i] != '0' && Prime.prime?(s[i .. -1].to_i)
}
}
EDIT: This can actually be optimised further though - if ABCD
turns out not to be a truncatable prime, ZABCD
does not need to be tested:
require 'set'
require 'prime'
Set.new.tap { |f|
Prime.each(10000) { |p|
s = p.to_s
f << p if p < 10 || (s[1] != '0' && f.include?(s[1 .. -1].to_i))
}
}.reject { |p| p < 10 }
EDIT: Forgot about the no zeroes requirement. Added. But being on mobile now, can't check if still running OK.
Upvotes: 4