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.
Files changed (55) hide show
  1. data/VERSION +1 -1
  2. data/lib/numb/abundancy.rb +2 -0
  3. data/lib/numb/achain.rb +99 -0
  4. data/lib/numb/almost_perfect.rb +2 -0
  5. data/lib/numb/amicable.rb +2 -4
  6. data/lib/numb/delannoy.rb +1 -0
  7. data/lib/numb/fibonacci.rb +1 -1
  8. data/lib/numb/goldbach.rb +6 -1
  9. data/lib/numb/harshad.rb +3 -2
  10. data/lib/numb/highly_composite.rb +2 -0
  11. data/lib/numb/hoax.rb +7 -0
  12. data/lib/numb/idempotent.rb +6 -0
  13. data/lib/numb/infinitary_divisors.rb +15 -0
  14. data/lib/numb/infinitary_perfect.rb +6 -0
  15. data/lib/numb/integer_p.rb +1 -1
  16. data/lib/numb/knuth.rb +15 -0
  17. data/lib/numb/lah.rb +6 -0
  18. data/lib/numb/motzkin.rb +16 -0
  19. data/lib/numb/multiamicable.rb +7 -0
  20. data/lib/numb/m/303/251nage.rb +23 -0
  21. data/lib/numb/nexus.rb +7 -0
  22. data/lib/numb/nsw.rb +16 -0
  23. data/lib/numb/pandigital.rb +6 -0
  24. data/lib/numb/persistent.rb +6 -0
  25. data/lib/numb/prime_power.rb +6 -0
  26. data/lib/numb/pronic.rb +1 -0
  27. data/lib/numb/square.rb +2 -2
  28. data/lib/numb/sum_of_infinitary_divisors.rb +9 -0
  29. data/lib/numb/superabundant.rb +12 -2
  30. data/lib/numb/vampire.rb +6 -5
  31. data/lib/numb.rb +17 -0
  32. data/spec/numb/achain_spec.rb +39 -0
  33. data/spec/numb/fibonacci_spec.rb +1 -1
  34. data/spec/numb/hoax_spec.rb +21 -0
  35. data/spec/numb/idempotent_spec.rb +59 -0
  36. data/spec/numb/infinitary_divisors_spec.rb +57 -0
  37. data/spec/numb/infinitary_perfect_spec.rb +21 -0
  38. data/spec/numb/integer_p_spec.rb +4 -4
  39. data/spec/numb/knuth_spec.rb +29 -0
  40. data/spec/numb/lah_spec.rb +61 -0
  41. data/spec/numb/motzkin_spec.rb +30 -0
  42. data/spec/numb/multiamicable_spec.rb +26 -0
  43. data/spec/numb/m/303/251nage_spec.rb +31 -0
  44. data/spec/numb/nexus_spec.rb +42 -0
  45. data/spec/numb/nsw_spec.rb +32 -0
  46. data/spec/numb/pandigital_spec.rb +29 -0
  47. data/spec/numb/persistent_spec.rb +44 -0
  48. data/spec/numb/prime_power_spec.rb +66 -0
  49. data/spec/numb/rough_spec.rb +37 -37
  50. data/spec/numb/square_spec.rb +16 -12
  51. data/spec/numb/sum_of_infinitary_divisors_spec.rb +15 -0
  52. data/spec/numb/superabundant_spec.rb +7 -7
  53. data/spec/numb/vampire_spec.rb +11 -11
  54. data/spec/spec_helper.rb +1 -1
  55. metadata +50 -2
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.138.0
1
+ 0.152.0
@@ -3,4 +3,6 @@ class Integer
3
3
  def abundancy
4
4
  Rational(σ, self)
5
5
  end
6
+
7
+ memoize :abundancy
6
8
  end
@@ -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
@@ -3,4 +3,6 @@ class Integer
3
3
  return true if self == 1
4
4
  proper_divisors.reduce(:+) == self - 1
5
5
  end
6
+
7
+ alias :least_deficient? :almost_perfect?
6
8
  end
data/lib/numb/amicable.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  class Integer
2
2
  def amicable?(other)
3
- return false if other == self
4
- [self, other].map do |n|
5
- n.proper_divisors.reduce(:+)
6
- end == [other, self]
3
+ n, m = [self, other].minmax
4
+ m.multiamicable?(n, 1, 1)
7
5
  end
8
6
  end
data/lib/numb/delannoy.rb CHANGED
@@ -22,4 +22,5 @@ class Integer
22
22
  return 1 if b.zero? or a.zero?
23
23
  [(a - 1).delannoy(b), a.delannoy(b - 1), (a - 1).delannoy(b - 1)].reduce(:+)
24
24
  end
25
+ memoize :delannoy
25
26
  end
@@ -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}.one? &:square?
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
@@ -1,8 +1,9 @@
1
1
  # coding: utf-8
2
2
  class Integer
3
3
  def harshad?
4
- return false unless self >= 1
5
- (self % digital_sum) == 0
4
+ self >= 1 and (self % digital_sum).zero?
6
5
  end
6
+
7
7
  alias :niven? :harshad?
8
+ alias :multidigital? :harshad?
8
9
  end
@@ -7,4 +7,6 @@ class Integer
7
7
  x.number_of_divisors >= n_divisors
8
8
  end
9
9
  end
10
+
11
+ alias :julian? :highly_composite?
10
12
  end
data/lib/numb/hoax.rb ADDED
@@ -0,0 +1,7 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def hoax?
4
+ return false unless composite?
5
+ sum_of_digits == prime_factors.uniq.map{|f| f.sum_of_digits}.reduce(:+)
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def idempotent(k)
4
+ (k.choose(self) * (self**(k - self))).to_i
5
+ end
6
+ end
@@ -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
@@ -0,0 +1,6 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def infinitary_perfect?
4
+ σ∞ == 2*self
5
+ end
6
+ end
@@ -6,6 +6,6 @@ end
6
6
 
7
7
  class Float
8
8
  def integer?
9
- round(10) == to_i
9
+ !!(sprintf("%f", self) =~ /\.0+$/)
10
10
  end
11
11
  end
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
@@ -0,0 +1,6 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def lah(k)
4
+ ((self-1).choose(k-1) * Rational(factorial, k.factorial)).to_i
5
+ end
6
+ end
@@ -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,7 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def multiamicable?(m, a, b)
4
+ return false unless m != self and m < self and a.positive? and b.positive?
5
+ m.σ - m == a*self and σ - self == b*m
6
+ end
7
+ 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
@@ -0,0 +1,7 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def nexus(d)
4
+ (self + 1)**d.succ - self**d.succ
5
+ end
6
+ end
7
+
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
@@ -0,0 +1,6 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def pandigital?
4
+ (0..9).all?{|d| digits.include? d}
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def persistent?(n)
4
+ (1..n).all?{|x| (x * self).pandigital?}
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def prime_power?(k=nil)
4
+ self == 1 or (primaries.size == 1 and (not k or primaries.first.last == k))
5
+ end
6
+ end
data/lib/numb/pronic.rb CHANGED
@@ -5,4 +5,5 @@ class Integer
5
5
  end
6
6
 
7
7
  alias :heteromecic? :pronic?
8
+ alias :oblong? :pronic?
8
9
  end
data/lib/numb/square.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  class Integer
3
3
  def square?
4
- return false if self < 0
5
- sqrt.integer?
4
+ return false unless zero? or (positive? and to_s(16)[-1] =~ /[0149]/)
5
+ (sq = sqrt).finite? ? sq.integer? : nil
6
6
  end
7
7
  end
@@ -0,0 +1,9 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def σ∞
4
+ infinitary_divisors.reduce :+
5
+ end
6
+
7
+ alias :sum_of_infinitary_divisors :σ∞
8
+ alias :isigma :σ∞
9
+ end
@@ -2,7 +2,17 @@
2
2
  class Integer
3
3
  def superabundant?
4
4
  return true if self == 1
5
- sod_over_self = Rational(σ, self)
6
- (self - 1).downto(1).all?{|m| Rational(m.σ, m) < sod_over_self}
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 !prime? and digits.size.even?
5
- digits.permutation.map do |perm|
6
- [:first,:last].map {|pos| perm.send(pos,(digits.size/2)).join.to_i }.sort
7
- end.uniq.any? do |fangs|
8
- fangs.reduce(:*) == self
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
@@ -12,7 +12,7 @@ describe Integer, "#fibonacci?" do
12
12
  end
13
13
  end
14
14
 
15
- @seq.invert.sample(10).each do |n|
15
+ @seq.invert.sample(100).each do |n|
16
16
  it "returns false for non-Fibonacci number #{n}" do
17
17
  n.should_not be_fibonacci
18
18
  end
@@ -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