Rubyの Prime
クラスには、素数を判定・列挙したり素因数分解するメソッドが実装されている。しかし素因数分解までであり、約数に関する操作は無い。約数を列挙したり、その個数を数えたりしたかったので、素因数分解のメソッドを利用して追加実装してみた。
実装
require 'prime'
class Prime
def each_divisor(n, &block)
pf = prime_division(n)
num = -> { pf.inject(1) { |prod, (_, exp)| prod * exp.succ } }
Enumerator.new(num) { |y| __each_divisor__(1, pf, &y.method(:<<)) }
.tap { |enum| enum.each(&block) }
end
private def __each_divisor__(d, ary, &block)
return yield(d) if ary.empty?
ary = ary.dup
prime, exp = ary.pop
0.upto(exp) { __each_divisor__(d, ary, &block); d *= prime }
end
end
使用例
prime = Prime.instance
# 約数の個数
prime.each_divisor(60).size
#=> 12
# 約数でループ(ソートはされない)
prime.each_divisor(60) { |d| print d, ' ' }; print "\n"
#=> 1 2 4 3 6 12 5 10 20 15 30 60
# Enumerableなメソッドを作用
prime.each_divisor(60).select { |d| d * d <= 60 }
#=> [1, 2, 4, 3, 6, 5]
# 1でも正しく動作
prime.each_divisor(1).to_a
#=> [1]
なお、メソッド定義はインスタンスメソッドとして実施したが、 Prime
クラスの計らいでクラスメソッドとしても呼び出せる。( Prime.each_divisor(60)
といった感じ)