Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions lib/prime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,34 @@
require "forwardable"

class Integer
# Returns the positive divisors of +self+ if +self+ is positive.
#
# == Example
# 6.divisors #=> [1, 2, 3, 6]
# 7.divisors #=> [1, 7]
# 8.divisors #=> [1, 2, 4, 8]
def divisors
if prime?
[1, self]
elsif self == 1
[1]
else
xs = prime_division.map{ |p, n| Array.new(n + 1){ |e| p**e } }
x = xs.pop
x.product(*xs).map{ |t| t.inject(:*) }.sort
end
end

# Iterates the given block for each divisor of +self+.
#
# == Example
# ds = []
# 10.divisors{ |d| ds << d }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# 10.divisors{ |d| ds << d }
# 10.each_divisor{ |d| ds << d }

# ds #=> [1, 2, 5, 10]
def each_divisor
block_given? ? divisors.each{ |d| yield(d) } : enum_for(:each_divisor)
end

# Re-composes a prime factorization and returns the product.
#
# See Prime#int_from_prime_division for more details.
Expand Down
49 changes: 49 additions & 0 deletions test/test_prime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,55 @@ def test_rewind
end

class TestInteger < Test::Unit::TestCase
def test_divisors
assert_equal [1], 1.divisors
assert_equal [1, 2], 2.divisors
assert_equal [1, 3], 3.divisors
assert_equal [1, 2, 4], 4.divisors
assert_equal [1, 5], 5.divisors
assert_equal [1, 2, 3, 6], 6.divisors
assert_equal [1, 7], 7.divisors
assert_equal [1, 2, 4, 8], 8.divisors
assert_equal [1, 3, 9], 9.divisors
assert_equal [1, 2, 5, 10], 10.divisors
assert_equal [1, 2, 4, 5, 10, 20, 25, 50, 100], 100.divisors

# large prime number
assert_equal [1, 2**31-1], (2**31-1).divisors
assert_equal [1, 1_000_000_007], 1_000_000_007.divisors
assert_equal [1, 1_000_000_009], 1_000_000_009.divisors
assert_equal [1, 67_280_421_310_721], 67_280_421_310_721.divisors

# large composite number
p1 = 2**13-1
p2 = 2**17-1
assert_equal [1, p1, p2, p1 * p2], (p1 * p2).divisors

assert_raises(ZeroDivisionError){ 0.divisors }
assert_equal [-1, 1], -1.divisors
assert_equal [-2, -1, 1, 2], -2.divisors
assert_equal [-3, -1, 1, 3], -3.divisors
assert_equal [-4, -2, -1, 1, 2, 4], -4.divisors
assert_equal [-6, -3, -2, -1, 1, 2, 3, 6], -6.divisors
end

def test_each_divisor
d10 = []
10.each_divisor{ |d| d10 << d }
assert_equal [1, 2, 5, 10], d10

assert_equal [1], 1.each_divisor.to_a
assert_equal [1, 3], 3.each_divisor.to_a
assert_equal [1, 2, 4], 4.each_divisor.to_a
assert_equal [1, 2, 3, 6], 6.each_divisor.to_a

assert_raises(ZeroDivisionError){ 0.each_divisor.to_a }
assert_equal [-1, 1], -1.each_divisor.to_a
assert_equal [-2, -1, 1, 2], -2.each_divisor.to_a
assert_equal [-4, -2, -1, 1, 2, 4], -4.each_divisor.to_a
assert_equal [-6, -3, -2, -1, 1, 2, 3, 6], -6.each_divisor.to_a
end

def test_prime_division
pd = PRIMES.inject(&:*).prime_division
assert_equal PRIMES.map{|p| [p, 1]}, pd
Expand Down