numb 0.138.0 → 0.152.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/lib/numb/abundancy.rb +2 -0
- data/lib/numb/achain.rb +99 -0
- data/lib/numb/almost_perfect.rb +2 -0
- data/lib/numb/amicable.rb +2 -4
- data/lib/numb/delannoy.rb +1 -0
- data/lib/numb/fibonacci.rb +1 -1
- data/lib/numb/goldbach.rb +6 -1
- data/lib/numb/harshad.rb +3 -2
- data/lib/numb/highly_composite.rb +2 -0
- data/lib/numb/hoax.rb +7 -0
- data/lib/numb/idempotent.rb +6 -0
- data/lib/numb/infinitary_divisors.rb +15 -0
- data/lib/numb/infinitary_perfect.rb +6 -0
- data/lib/numb/integer_p.rb +1 -1
- data/lib/numb/knuth.rb +15 -0
- data/lib/numb/lah.rb +6 -0
- data/lib/numb/motzkin.rb +16 -0
- data/lib/numb/multiamicable.rb +7 -0
- data/lib/numb/m/303/251nage.rb +23 -0
- data/lib/numb/nexus.rb +7 -0
- data/lib/numb/nsw.rb +16 -0
- data/lib/numb/pandigital.rb +6 -0
- data/lib/numb/persistent.rb +6 -0
- data/lib/numb/prime_power.rb +6 -0
- data/lib/numb/pronic.rb +1 -0
- data/lib/numb/square.rb +2 -2
- data/lib/numb/sum_of_infinitary_divisors.rb +9 -0
- data/lib/numb/superabundant.rb +12 -2
- data/lib/numb/vampire.rb +6 -5
- data/lib/numb.rb +17 -0
- data/spec/numb/achain_spec.rb +39 -0
- data/spec/numb/fibonacci_spec.rb +1 -1
- data/spec/numb/hoax_spec.rb +21 -0
- data/spec/numb/idempotent_spec.rb +59 -0
- data/spec/numb/infinitary_divisors_spec.rb +57 -0
- data/spec/numb/infinitary_perfect_spec.rb +21 -0
- data/spec/numb/integer_p_spec.rb +4 -4
- data/spec/numb/knuth_spec.rb +29 -0
- data/spec/numb/lah_spec.rb +61 -0
- data/spec/numb/motzkin_spec.rb +30 -0
- data/spec/numb/multiamicable_spec.rb +26 -0
- data/spec/numb/m/303/251nage_spec.rb +31 -0
- data/spec/numb/nexus_spec.rb +42 -0
- data/spec/numb/nsw_spec.rb +32 -0
- data/spec/numb/pandigital_spec.rb +29 -0
- data/spec/numb/persistent_spec.rb +44 -0
- data/spec/numb/prime_power_spec.rb +66 -0
- data/spec/numb/rough_spec.rb +37 -37
- data/spec/numb/square_spec.rb +16 -12
- data/spec/numb/sum_of_infinitary_divisors_spec.rb +15 -0
- data/spec/numb/superabundant_spec.rb +7 -7
- data/spec/numb/vampire_spec.rb +11 -11
- data/spec/spec_helper.rb +1 -1
- metadata +50 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.152.0
|
data/lib/numb/abundancy.rb
CHANGED
data/lib/numb/achain.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module AChain
|
3
|
+
def self.sequence(*terms)
|
4
|
+
chain, perms = ([1] + terms), {}
|
5
|
+
possible =->(term) do
|
6
|
+
return true if perms.values.include?(term)
|
7
|
+
options = chain.uniq.select{|perm| perm < term}
|
8
|
+
(options * 2).permutation(2).to_a.uniq.any? do |perm|
|
9
|
+
(perms[perm] ||= perm.reduce(:+)) == term
|
10
|
+
end
|
11
|
+
end
|
12
|
+
loop do
|
13
|
+
catch(:restart) do
|
14
|
+
(chain = chain.sort.reverse).each_with_index do |term, i|
|
15
|
+
return chain.sort.uniq if term == 1
|
16
|
+
next if possible[term]
|
17
|
+
chain << if term >= (chain[i.succ] * 3)
|
18
|
+
term.even? ? term / 2 : term - 1
|
19
|
+
else
|
20
|
+
term - chain[i.succ]
|
21
|
+
end
|
22
|
+
throw :restart
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.factor(n)
|
29
|
+
build_tree = ->(n) do
|
30
|
+
return if n == 1
|
31
|
+
p = n.prime_factors.first
|
32
|
+
q = n/p
|
33
|
+
q, p = p - 1, 1 if p == n
|
34
|
+
{left: q, value: n, right: p}.tap do |node|
|
35
|
+
node[:right] = build_tree[p] if p > 1
|
36
|
+
node[:left] = build_tree[q] if q > 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
current, chain = (t = build_tree[root = n]), [x = 1]
|
41
|
+
|
42
|
+
make_chain =->(node) do
|
43
|
+
[:right, :left].each do |dir|
|
44
|
+
if node[dir] == 2 then chain << x *= 2
|
45
|
+
elsif node[dir] and node[dir] != 1
|
46
|
+
x = make_chain[node[dir]]
|
47
|
+
end
|
48
|
+
node[:x] = x if dir == :right
|
49
|
+
end
|
50
|
+
|
51
|
+
if node[:value] == root and node[:right] == 1
|
52
|
+
if r = node[:right]
|
53
|
+
x += r.respond_to?(:fetch) ? r[:x] || 0 : r
|
54
|
+
end
|
55
|
+
chain << x
|
56
|
+
elsif node[:value] != root and node[:right] == 1
|
57
|
+
x += node[:x] if node.respond_to?(:fetch) and node[:x]
|
58
|
+
node.delete(:x)
|
59
|
+
chain << x
|
60
|
+
end
|
61
|
+
x
|
62
|
+
end
|
63
|
+
make_chain[t]
|
64
|
+
chain
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.window_brute(n)
|
68
|
+
(1..n.to_s(2).count('1')).map {|w| window(n,w)}.min_by(&:size)
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.window(n,w=3)
|
72
|
+
n = [*n.base(2).chars].map(&:to_i)
|
73
|
+
windows, zeroes = [[]], []
|
74
|
+
n.each do |bit|
|
75
|
+
if bit.zero? then zeroes << bit
|
76
|
+
elsif (zeroes.size + 1 + windows.last.size) > w
|
77
|
+
windows << zeroes.pop(zeroes.size) << [1]
|
78
|
+
else windows[-1] += zeroes.pop(zeroes.size) << 1
|
79
|
+
end
|
80
|
+
end
|
81
|
+
windows << zeroes unless zeroes.empty?
|
82
|
+
windows.map!{|w| [w, w.join.to_i(2).to_i]}
|
83
|
+
|
84
|
+
x = windows.first.last
|
85
|
+
self.sequence(*windows.map(&:last).reject(&:zero?).uniq).tap do |chain|
|
86
|
+
windows[1..-1].each do |bits, value|
|
87
|
+
bits.each {|bit| chain << x *= 2}
|
88
|
+
chain << x += value
|
89
|
+
end
|
90
|
+
end.sort.uniq
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Integer
|
95
|
+
def achain
|
96
|
+
self == 1 ? [1]
|
97
|
+
: [AChain.factor(self), AChain.window_brute(self)].min_by(&:size)
|
98
|
+
end
|
99
|
+
end
|
data/lib/numb/almost_perfect.rb
CHANGED
data/lib/numb/amicable.rb
CHANGED
data/lib/numb/delannoy.rb
CHANGED
data/lib/numb/fibonacci.rb
CHANGED
@@ -3,6 +3,6 @@ class Integer
|
|
3
3
|
return true if self == 1
|
4
4
|
# Posamentier, Alfred; Lehmann, Ingmar (2007). The (Fabulous) FIBONACCI
|
5
5
|
# Numbers. Prometheus Books. pp. 305
|
6
|
-
[4, -4].map{|x| (5 * (self**2)) + x}.
|
6
|
+
[4, -4].map{|x| (5 * (self**2)) + x}.any? &:square?
|
7
7
|
end
|
8
8
|
end
|
data/lib/numb/goldbach.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
class Integer
|
2
2
|
def goldbach?
|
3
3
|
return false unless even? and self > 2
|
4
|
-
downto(2).any?{|n| n.prime? and (self - n).prime?}
|
4
|
+
#downto(2).any?{|n| n.prime? and (self - n).prime?}
|
5
|
+
Prime.each do |prime|
|
6
|
+
next if prime == 2
|
7
|
+
return true if (self - prime).prime?
|
8
|
+
return false if prime >= self
|
9
|
+
end
|
5
10
|
end
|
6
11
|
end
|
data/lib/numb/harshad.rb
CHANGED
data/lib/numb/hoax.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
class Integer
|
3
|
+
def infinitary_divisors
|
4
|
+
pf = Hash[prime_factors.uniq.map{|f| [f, 0]}]
|
5
|
+
bin = divisors.map do |d|
|
6
|
+
prime_divisors = pf.map(&:first)
|
7
|
+
[d, pf.merge(Hash[d.primaries]).
|
8
|
+
values.
|
9
|
+
map{|v| sprintf("%.#{to_s(2).size}b", v)}.join]
|
10
|
+
end
|
11
|
+
bin = Hash[bin]
|
12
|
+
target = bin[self].chars.map.with_index.to_a.select{|a,b| a == '0'}.map(&:last)
|
13
|
+
bin.select{|d,b| target.all?{|i| b[i] == '0'}}.keys.sort
|
14
|
+
end
|
15
|
+
end
|
data/lib/numb/integer_p.rb
CHANGED
data/lib/numb/knuth.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
class Integer
|
3
|
+
def knuth
|
4
|
+
return 1 if zero?
|
5
|
+
n = self - 1
|
6
|
+
1 + [2 * (n/2).knuth, 3 * (n/3).knuth].min
|
7
|
+
end
|
8
|
+
|
9
|
+
def knuth?
|
10
|
+
downto(0) do |n|
|
11
|
+
next if (k = n.knuth) > self
|
12
|
+
return k == self ? true : false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/numb/lah.rb
ADDED
data/lib/numb/motzkin.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
class Integer
|
3
|
+
def motzkin
|
4
|
+
n = self
|
5
|
+
return 1 if n <= 1
|
6
|
+
((3 * (n - 1) * (n - 2).motzkin) + (2 * n).succ * (n - 1).motzkin) / (n + 2)
|
7
|
+
end
|
8
|
+
|
9
|
+
def motzkin?
|
10
|
+
(1..self).each do |n|
|
11
|
+
m = n.motzkin
|
12
|
+
next if m < self
|
13
|
+
return m == self ? true : false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
class Integer
|
3
|
+
def ménage
|
4
|
+
return 1 if zero? # FIXME: Check this
|
5
|
+
return 0 unless self > 1
|
6
|
+
(0..self).map do |k|
|
7
|
+
Rational(2 * self, 2 * self - k) *
|
8
|
+
((2 * self) - k).choose(k) *
|
9
|
+
(self - k).factorial *
|
10
|
+
(-1)**k
|
11
|
+
end.reduce(:+).to_i
|
12
|
+
end
|
13
|
+
|
14
|
+
def ménage?
|
15
|
+
(1..self).each do |n|
|
16
|
+
next if (m = n.ménage) < self
|
17
|
+
return m == self ? true : false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
alias :menage :ménage
|
22
|
+
alias :menage? :ménage?
|
23
|
+
end
|
data/lib/numb/nexus.rb
ADDED
data/lib/numb/nsw.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
class Integer
|
3
|
+
def nsw
|
4
|
+
case self
|
5
|
+
when 0 then 1
|
6
|
+
when 1 then 7
|
7
|
+
else 6 * (self - 1).nsw - (self - 2).nsw
|
8
|
+
end
|
9
|
+
end
|
10
|
+
memoize(:nsw)
|
11
|
+
|
12
|
+
def nsw?
|
13
|
+
m = self
|
14
|
+
(rhs = (m**2).succ).divides?(2) and 2 * ((rhs/2).isqrt**2) == rhs
|
15
|
+
end
|
16
|
+
end
|
data/lib/numb/pronic.rb
CHANGED
data/lib/numb/square.rb
CHANGED
data/lib/numb/superabundant.rb
CHANGED
@@ -2,7 +2,17 @@
|
|
2
2
|
class Integer
|
3
3
|
def superabundant?
|
4
4
|
return true if self == 1
|
5
|
-
|
6
|
-
|
5
|
+
# Constraints due to "Abundant Numbers and the Riemann Hypothesis",
|
6
|
+
# Briggs, 2006, Experimental Mathematics, vol. 15, no. 2
|
7
|
+
ex = primaries.map(&:last)
|
8
|
+
return false unless [ex.last, ex.first] == ex.minmax
|
9
|
+
primaries[1..-1].all? do |b, e|
|
10
|
+
(e - (ex[0] * Math.log(b, primaries[0][0])).floor <= 1) and e < 2**(ex[0] + 2)
|
11
|
+
end or return false
|
12
|
+
return false unless [4, 36].include?(self) or ex.last == 1
|
13
|
+
1.upto(self - 1).all? do |m|
|
14
|
+
m.abundancy < abundancy
|
15
|
+
end
|
7
16
|
end
|
17
|
+
memoize :superabundant?
|
8
18
|
end
|
data/lib/numb/vampire.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
class Integer
|
3
3
|
def vampire?
|
4
|
-
return false unless
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
return false unless composite? and digits.size.even?
|
5
|
+
seen = {}
|
6
|
+
digits.permutation.any? do |perm|
|
7
|
+
fangs = [:first,:last].map {|pos| perm.send(pos,(digits.size/2)).join.to_i }.sort
|
8
|
+
next if seen.key?(fangs)
|
9
|
+
seen[fangs] = fangs.reduce(:*) == self
|
9
10
|
end
|
10
11
|
end
|
11
12
|
end
|
data/lib/numb.rb
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
module Memoize
|
3
|
+
def memoize(sym)
|
4
|
+
aka = "_#{sym}".to_sym
|
5
|
+
alias_method aka, sym
|
6
|
+
@@NUMB ||= {}
|
7
|
+
Integer.send(:define_method, sym) do |*args|
|
8
|
+
@@NUMB[[self, sym, args]] ||= send(aka, *args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
2
12
|
|
13
|
+
[Integer, Bignum].each do |klass|
|
14
|
+
class << klass
|
15
|
+
include Memoize
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
3
19
|
class Integer
|
4
20
|
def number_of_distinct_prime_factors
|
5
21
|
prime_factors.uniq.size
|
@@ -40,6 +56,7 @@ class Integer
|
|
40
56
|
(1..isqrt).select { |n| (self % n).zero? }.
|
41
57
|
map {|n| [n, self/n]}.flatten.uniq
|
42
58
|
end
|
59
|
+
memoize :divisors
|
43
60
|
|
44
61
|
def sum_of_divisors
|
45
62
|
@sod ||= divisors.reduce(:+)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
describe Integer, "#achain" do
|
3
|
+
# A003313
|
4
|
+
@seq = [0,1,2,2,3,3,4,3,4,4,5,4,5,5,5,4,5,5,6,5,6,6,6,5,6,6,6,6,7,6,7,5,6,
|
5
|
+
6,7,6,7,7,7,6,7,7,7,7,7,7,8,6,7,7,7,7,8,7,8,7,8,8,8,7,8,8,8,6,7,7,
|
6
|
+
8,7,8,8,9,7,8,8,8,8,8,8,9,7,8,8,8,8,8,8,9,8,9,8,9,8,9,9,9,7,8,8,8,8,]
|
7
|
+
|
8
|
+
@seq.to_enum.with_index(1) do |len, n|
|
9
|
+
achain = n.achain
|
10
|
+
|
11
|
+
it "returns an addition chain of #{len} terms for #{n}" do
|
12
|
+
(achain.size - 1).should == len
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns an addition chain for #{n} that ends with #{n}" do
|
16
|
+
achain.last.should == n
|
17
|
+
end
|
18
|
+
|
19
|
+
it "returns an addition chain for #{n} that begins with 1" do
|
20
|
+
achain.first.should == 1
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns an addition chain for #{n} without any duplicate terms" do
|
24
|
+
achain.uniq.should == achain
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns an addition chain for #{n} with terms ordered by smallest to largest" do
|
28
|
+
achain.sort.should == achain
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns an addition chain for #{n} whose terms are the sum of two preceeding terms" do
|
32
|
+
chain = achain.reverse
|
33
|
+
sums = (chain * 2).permutation(2).to_a.uniq.map{|perm| perm.reduce(:+)}
|
34
|
+
chain[0..-2].each do |t|
|
35
|
+
sums.should include(t)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/spec/numb/fibonacci_spec.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
describe Integer, "#hoax?" do
|
3
|
+
# A019506
|
4
|
+
@seq = [22,58,84,85,94,136,160,166,202,234,250,265,274,
|
5
|
+
308,319,336,346,355,361,364,382,391,424,438,454,
|
6
|
+
456,476,483,516,517,526,535,562,627,634,644,645,
|
7
|
+
650,654,660,663,690,702,706,732,735,762,778,855,
|
8
|
+
860]
|
9
|
+
|
10
|
+
@seq.each do |n|
|
11
|
+
it "returns true for hoax number #{n}" do
|
12
|
+
n.should be_hoax
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
@seq.to_seq.invert.each do |n|
|
17
|
+
it "returns false for non-hoax number #{n}" do
|
18
|
+
n.should_not be_hoax
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
describe Integer, "#idempotent" do
|
3
|
+
|
4
|
+
@seq = {
|
5
|
+
# A000027
|
6
|
+
1 => [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
|
7
|
+
20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,
|
8
|
+
36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
|
9
|
+
52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,
|
10
|
+
68,69,70,71,72,73,74,75,76,77],
|
11
|
+
# A001788
|
12
|
+
2 => [0,1,6,24,80,240,672,1792,4608,11520,28160,67584,
|
13
|
+
159744,372736,860160,1966080,4456448,10027008,
|
14
|
+
22413312,49807360,110100480,242221056,530579456,
|
15
|
+
1157627904,2516582400,5452595200,11777605632].reject(&:zero?),
|
16
|
+
# A036216
|
17
|
+
3 => [1,12,90,540,2835,13608,61236,262440,1082565,
|
18
|
+
4330260,16888014,64481508,241805655,892820880,
|
19
|
+
3252418920,11708708112,41712272649,147219785820,
|
20
|
+
515269250370,1789882659180,6175095174171,
|
21
|
+
21171754882872],
|
22
|
+
# A040075
|
23
|
+
4 => [1,20,240,2240,17920,129024,860160,5406720,
|
24
|
+
32440320,187432960,1049624576,5725224960,
|
25
|
+
30534533120,159719096320,821412495360,
|
26
|
+
4161823309824,20809116549120,102821517066240,
|
27
|
+
502682972323840],
|
28
|
+
# A050982
|
29
|
+
5 => [1,30,525,7000,78750,787500,7218750,61875000,
|
30
|
+
502734375,3910156250,29326171875,213281250000,
|
31
|
+
1510742187500,10458984375000,70971679687500,
|
32
|
+
473144531250000,3105010986328125,
|
33
|
+
20091247558593750],
|
34
|
+
# A050988
|
35
|
+
6 => [1,42,1008,18144,272160,3592512,43110144,
|
36
|
+
480370176,5043886848,50438868480,484213137408,
|
37
|
+
4489976365056,40409787285504,354362750042112,
|
38
|
+
3037395000360960,25514118003032064],
|
39
|
+
# A050989
|
40
|
+
7 => [1,56,1764,41160,792330,13311144,201885684,
|
41
|
+
2826399576,37096494435,461645264080,5493578642552,
|
42
|
+
62926446269232,697434779483988,7510836086750640,
|
43
|
+
78863778910881720,809668130151718992],
|
44
|
+
}
|
45
|
+
|
46
|
+
@seq.each do |n, values|
|
47
|
+
(1...n).each do |k|
|
48
|
+
it "returns 0 when n=#{n} and k=#{k}" do
|
49
|
+
n.idempotent(k).should be_zero
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
values.to_enum.with_index(n).each do |idem, k|
|
54
|
+
it "returns #{idem} for n=#{n} and k=#{k}" do
|
55
|
+
n.idempotent(k).should == idem
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
describe Integer, "#infinitary_divisors" do
|
3
|
+
# A077609
|
4
|
+
@seq = [
|
5
|
+
[1],
|
6
|
+
[1,2],
|
7
|
+
[1,3],
|
8
|
+
[1,4],
|
9
|
+
[1,5],
|
10
|
+
[1,2,3,6],
|
11
|
+
[1,7],
|
12
|
+
[1,2,4,8],
|
13
|
+
[1,9],
|
14
|
+
[1,2,5,10],
|
15
|
+
[1,11],
|
16
|
+
[1,3,4,12],
|
17
|
+
[1,13],
|
18
|
+
[1,2,7,14],
|
19
|
+
[1,3,5,15],
|
20
|
+
[1,16],
|
21
|
+
[1,17],
|
22
|
+
[1,2,9,18],
|
23
|
+
[1,19],
|
24
|
+
[1,4,5,20],
|
25
|
+
[1,3,7,21],
|
26
|
+
[1,2,11,22],
|
27
|
+
[1,23],
|
28
|
+
[1,2,3,4,6,8,12,24],
|
29
|
+
[1,25],
|
30
|
+
[1,2,13,26],
|
31
|
+
[1,3,9,27],
|
32
|
+
[1,4,7,28],
|
33
|
+
[1,29],
|
34
|
+
#[1]
|
35
|
+
]
|
36
|
+
|
37
|
+
@seq.each do |id|
|
38
|
+
id.sort!
|
39
|
+
n = id.last
|
40
|
+
it "returns #{id} for #{n}" do
|
41
|
+
n.infinitary_divisors.should == id
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# A037445
|
46
|
+
@counts = [1,2,2,2,2,4,2,4,2,4,2,4,2,4,4,2,2,4,2,4,4,4,2,8,
|
47
|
+
2,4,4,4,2,8,2,4,4,4,4,4,2,4,4,8,2,8,2,4,4,4,2,4,2,
|
48
|
+
4,4,4,2,8,4,8,4,4,2,8,2,4,4,4,4,8,2,4,4,8,2,8,2,4,
|
49
|
+
4,4,4,8,2,4,2,4,2,8,4,4,4,8,2,8,4,4,4,4,4,8,2,4,4,
|
50
|
+
4,2,8,2,8,8]
|
51
|
+
|
52
|
+
@counts.to_enum.with_index(1).each do |c, n|
|
53
|
+
it "returns #{c} infinitary divisors for #{n}" do
|
54
|
+
n.infinitary_divisors.uniq.count.should == c
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
describe Integer, "#infinitary_perfect?" do
|
3
|
+
# A007357
|
4
|
+
@seq = [6,60,90,36720,12646368,22276800,126463680,
|
5
|
+
4201148160,28770487200,287704872000,1446875426304,
|
6
|
+
2548696550400,14468754263040,590325173932032,
|
7
|
+
3291641594841600,8854877608980480,
|
8
|
+
32916415948416000].first(7)
|
9
|
+
|
10
|
+
@seq.each do |n|
|
11
|
+
it "returns true for infinitary perfect number #{n}" do
|
12
|
+
n.should be_infinitary_perfect
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
@seq.to_seq.invert.sample(7).each do |n|
|
17
|
+
it "returns false for non-infinitary perfect number #{n}" do
|
18
|
+
n.should_not be_infinitary_perfect
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|