この記事はOkinawa.rb Advent Calendar 2018の3日目の記事です。
昨日は @hanachin_ さんのRe: Ruby で季節のような循環する概念を表したいでした。
明日は @hanachin_ さんのTracePointのenable(target: )は戻り値を書き換えるときべんりです。
シクシク素数のプログラムを見て書きたくなったので書きました
https://qiita.com/tbpgr/items/9f075537b927916f64d5
改良版
見ていて改良できそうなので書きました
require 'prime'
😭prime = Prime.each.lazy.select {|prime|
digits = prime.digits
digits.include?(4) || digits.include?(9)
}
puts 😭prime.take(ARGV.first.to_i).to_a.join(",")
ベンチマーク
ちょっと早い
require 'benchmark_driver'
Benchmark.driver do |x|
x.prelude <<~RUBY
require 'prime'
😭prime = Enumerator.new do |y|
a = 1
loop do
a += 1
loop { a.prime? && a.to_s.match(/[49]/) ? break : a += 1 }
y << a
end
end
😭prime.take(100)
😭prime2 = Prime.each.lazy.select {|prime|
digits = prime.digits
digits.include?(4) || digits.include?(9)
}
😭prime2.take(100)
RUBY
x.report 'tbpgr', '😭prime.take(100)'
x.report 'hanachin', '😭prime2.take(100).to_a'
end
% ruby -v /tmp/49.rb
ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]
Warming up --------------------------------------
tbpgr 1.871k i/s - 1.880k times in 1.004923s (534.53μs/i)
hanachin 4.642k i/s - 4.972k times in 1.071051s (215.42μs/i)
Calculating -------------------------------------
tbpgr 1.958k i/s - 5.612k times in 2.866668s (510.81μs/i)
hanachin 4.593k i/s - 13.926k times in 3.032325s (217.75μs/i)
Comparison:
hanachin: 4592.5 i/s
tbpgr: 1957.7 i/s - 2.35x slower
変更点
Prime.each
を使うとEnumeratorが取れるのでそれをそのまま使いました。
http://rurema.clear-code.com/2.5.0/method/Prime/s/each.html
そのままでは無限に素数を列挙しつづけるのでEnumerable#lazy
を使って遅延評価するようにしました。
http://rurema.clear-code.com/2.5.0/method/Enumerable/i/lazy.html
数値に4か9が含まれているか判定するためにInteger#digits
を利用しています。
http://rurema.clear-code.com/2.5.0/method/Integer/i/digits.html