numb 0.152.0 → 0.170.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 (156) hide show
  1. data/VERSION +1 -1
  2. data/lib/numb/bell.rb +9 -12
  3. data/lib/numb/bernoulli.rb +7 -8
  4. data/lib/numb/catalan.rb +1 -5
  5. data/lib/numb/divisors/abundant.rb +58 -0
  6. data/lib/numb/divisors/aliquot.rb +31 -0
  7. data/lib/numb/divisors/amicable.rb +38 -0
  8. data/lib/numb/divisors/perfect.rb +73 -0
  9. data/lib/numb/divisors.rb +389 -0
  10. data/lib/numb/entringer.rb +2 -0
  11. data/lib/numb/figurate.rb +138 -0
  12. data/lib/numb/in_sequence.rb +11 -0
  13. data/lib/numb/jacobsthal_lucas.rb +5 -6
  14. data/lib/numb/knuth.rb +1 -4
  15. data/lib/numb/lucas.rb +5 -5
  16. data/lib/numb/lucas2.rb +11 -0
  17. data/lib/numb/lychrel.rb +0 -4
  18. data/lib/numb/palindrome.rb +8 -0
  19. data/lib/numb/pell_lucas.rb +9 -0
  20. data/lib/numb/primes.rb +164 -0
  21. data/lib/numb/pronic.rb +1 -0
  22. data/lib/numb/q.rb +13 -0
  23. data/lib/numb/schr/303/266der.rb +20 -0
  24. data/lib/numb/segmented.rb +29 -0
  25. data/lib/numb/stirling.rb +9 -0
  26. data/lib/numb/stirling2.rb +9 -0
  27. data/lib/numb/strictly_non_palindromic.rb +1 -5
  28. data/lib/numb/super_catalan.rb +17 -0
  29. data/lib/numb/super_d.rb +6 -0
  30. data/lib/numb/takeuchi.rb +18 -0
  31. data/lib/numb/unhappy.rb +2 -0
  32. data/lib/numb.rb +1 -53
  33. data/spec/numb/first_with_n_divisors_spec.rb +15 -0
  34. data/spec/numb/highly_composite_spec.rb +1 -1
  35. data/spec/numb/jacobsthal_lucas_spec.rb +19 -11
  36. data/spec/numb/lucas2_spec.rb +30 -0
  37. data/spec/numb/lucas_spec.rb +17 -9
  38. data/spec/numb/minimal_spec.rb +1 -1
  39. data/spec/numb/near_square_spec.rb +54 -0
  40. data/spec/numb/octahedral_spec.rb +29 -0
  41. data/spec/numb/palindrome_spec.rb +43 -0
  42. data/spec/numb/pell_lucas_spec.rb +28 -0
  43. data/spec/numb/pentatope_spec.rb +15 -0
  44. data/spec/numb/primitive_abundant_spec.rb +21 -0
  45. data/spec/numb/pyramidal_spec.rb +42 -0
  46. data/spec/numb/q_spec.rb +31 -0
  47. data/spec/numb/schr/303/266der_spec.rb +28 -0
  48. data/spec/numb/segmented_spec.rb +29 -0
  49. data/spec/numb/square_part_spec.rb +15 -0
  50. data/spec/numb/star_spec.rb +29 -0
  51. data/spec/numb/stella_octangula_spec.rb +29 -0
  52. data/spec/numb/stirling2_spec.rb +23 -0
  53. data/spec/numb/stirling_spec.rb +23 -0
  54. data/spec/numb/super_catalan_spec.rb +29 -0
  55. data/spec/numb/super_d_spec.rb +68 -0
  56. data/spec/numb/takeuchi_spec.rb +28 -0
  57. data/spec/numb/tetrahedral_spec.rb +15 -0
  58. metadata +63 -100
  59. data/lib/numb/abundancy.rb +0 -8
  60. data/lib/numb/abundant.rb +0 -20
  61. data/lib/numb/achilles.rb +0 -15
  62. data/lib/numb/aliquot_sequence.rb +0 -13
  63. data/lib/numb/almost_perfect.rb +0 -8
  64. data/lib/numb/almost_prime.rb +0 -6
  65. data/lib/numb/amicable.rb +0 -6
  66. data/lib/numb/aspiring.rb +0 -8
  67. data/lib/numb/augmented_amicable.rb +0 -7
  68. data/lib/numb/balanced_prime.rb +0 -10
  69. data/lib/numb/betrothed.rb +0 -8
  70. data/lib/numb/breeder.rb +0 -9
  71. data/lib/numb/brilliant.rb +0 -7
  72. data/lib/numb/centered_cube.rb +0 -7
  73. data/lib/numb/centered_hexagonal.rb +0 -6
  74. data/lib/numb/centered_n_gonal.rb +0 -9
  75. data/lib/numb/centered_pentagonal.rb +0 -6
  76. data/lib/numb/centered_square.rb +0 -5
  77. data/lib/numb/centered_triangular.rb +0 -5
  78. data/lib/numb/composite.rb +0 -5
  79. data/lib/numb/coprime.rb +0 -9
  80. data/lib/numb/cube.rb +0 -5
  81. data/lib/numb/d.rb +0 -6
  82. data/lib/numb/decagonal.rb +0 -5
  83. data/lib/numb/deficient.rb +0 -19
  84. data/lib/numb/dihedral_prime.rb +0 -26
  85. data/lib/numb/dodecagonal.rb +0 -5
  86. data/lib/numb/e_divisors.rb +0 -10
  87. data/lib/numb/e_perfect.rb +0 -7
  88. data/lib/numb/economical.rb +0 -16
  89. data/lib/numb/emrip.rb +0 -15
  90. data/lib/numb/equidigital.rb +0 -18
  91. data/lib/numb/extravagant.rb +0 -18
  92. data/lib/numb/fermat_pseudoprime.rb +0 -9
  93. data/lib/numb/friendly.rb +0 -9
  94. data/lib/numb/full_reptend_prime.rb +0 -5
  95. data/lib/numb/giuga.rb +0 -7
  96. data/lib/numb/harshad.rb +0 -9
  97. data/lib/numb/heptagonal.rb +0 -5
  98. data/lib/numb/hexagonal.rb +0 -6
  99. data/lib/numb/highly_abundant.rb +0 -7
  100. data/lib/numb/highly_composite.rb +0 -12
  101. data/lib/numb/hoax.rb +0 -7
  102. data/lib/numb/hyperperfect.rb +0 -7
  103. data/lib/numb/impolite.rb +0 -6
  104. data/lib/numb/infinitary_divisors.rb +0 -15
  105. data/lib/numb/infinitary_perfect.rb +0 -6
  106. data/lib/numb/interprime.rb +0 -6
  107. data/lib/numb/k_perfect.rb +0 -8
  108. data/lib/numb/mersenne_prime.rb +0 -5
  109. data/lib/numb/minimal.rb +0 -8
  110. data/lib/numb/multiamicable.rb +0 -7
  111. data/lib/numb/myriagonal.rb +0 -5
  112. data/lib/numb/n_gonal.rb +0 -7
  113. data/lib/numb/next_prev_prime.rb +0 -13
  114. data/lib/numb/nth_prime.rb +0 -17
  115. data/lib/numb/number_of_divisors.rb +0 -22
  116. data/lib/numb/octagonal.rb +0 -5
  117. data/lib/numb/ore.rb +0 -8
  118. data/lib/numb/pentagonal.rb +0 -5
  119. data/lib/numb/perfect.rb +0 -8
  120. data/lib/numb/perfect_power.rb +0 -9
  121. data/lib/numb/polite.rb +0 -7
  122. data/lib/numb/powerful.rb +0 -10
  123. data/lib/numb/practical.rb +0 -26
  124. data/lib/numb/prime_count.rb +0 -16
  125. data/lib/numb/prime_signature.rb +0 -5
  126. data/lib/numb/primitive_pseudoperfect.rb +0 -5
  127. data/lib/numb/rhonda.rb +0 -6
  128. data/lib/numb/rough.rb +0 -5
  129. data/lib/numb/safe_prime.rb +0 -5
  130. data/lib/numb/semiperfect.rb +0 -20
  131. data/lib/numb/semiprime.rb +0 -6
  132. data/lib/numb/smith.rb +0 -7
  133. data/lib/numb/smooth.rb +0 -5
  134. data/lib/numb/sociable.rb +0 -6
  135. data/lib/numb/sophie_germain_prime.rb +0 -5
  136. data/lib/numb/square.rb +0 -7
  137. data/lib/numb/square_free.rb +0 -6
  138. data/lib/numb/square_triangular.rb +0 -5
  139. data/lib/numb/squared_triangular.rb +0 -5
  140. data/lib/numb/sublime.rb +0 -6
  141. data/lib/numb/sum_of_e_divisors.rb +0 -10
  142. data/lib/numb/sum_of_infinitary_divisors.rb +0 -9
  143. data/lib/numb/sum_of_unitary_divisors.rb +0 -5
  144. data/lib/numb/super_poulet.rb +0 -5
  145. data/lib/numb/superabundant.rb +0 -18
  146. data/lib/numb/superperfect.rb +0 -6
  147. data/lib/numb/triangular.rb +0 -6
  148. data/lib/numb/twin_prime.rb +0 -5
  149. data/lib/numb/unitary_amicable.rb +0 -7
  150. data/lib/numb/unitary_divisor.rb +0 -5
  151. data/lib/numb/unitary_perfect.rb +0 -7
  152. data/lib/numb/unitary_sociable.rb +0 -7
  153. data/lib/numb/untouchable.rb +0 -14
  154. data/lib/numb/unusual.rb +0 -5
  155. data/lib/numb/weird.rb +0 -8
  156. data/lib/numb/wieferich.rb +0 -6
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.152.0
1
+ 0.170.0
data/lib/numb/bell.rb CHANGED
@@ -1,16 +1,13 @@
1
1
  class Integer
2
2
  def bell?
3
- triangle = [[1]]
4
- r = 1
5
- loop do
6
- row = [triangle[r - 1][r - 1]]
7
- (1..r).each do |c|
8
- row << triangle[r - 1][c - 1] + row[c - 1]
9
- end
10
- triangle[r] = row
11
- return false if row.first > self
12
- return true if row.first == self
13
- r += 1
14
- end
3
+ in_sequence?(seq: :bell)
15
4
  end
5
+
6
+ def bell
7
+ n = self
8
+ return 1 if zero?
9
+ (0..(n-1)).map{|k| k.bell * (n-1).choose(k)}.reduce(:+)
10
+ end
11
+
12
+ memoize :bell
16
13
  end
@@ -2,13 +2,12 @@
2
2
  class Integer
3
3
  # TODO: Consider http://cims.nyu.edu/~harvey/bernmm/
4
4
  def bernoulli
5
- return -0.5.to_r if self == 1
6
- return 0.to_r if odd?
7
- a = []
8
- 0.upto(self) do |m|
9
- a[m] = Rational(1, m + 1)
10
- m.downto(1){|j| a[j - 1] = j * (a[j - 1] - a[j])}
11
- end
12
- a.first
5
+ return 1 if zero?
6
+ m = self
7
+ (m.zero? ? 1 : 0) - (0...m).map do |k|
8
+ m.choose(k) * Rational(k.bernoulli, m - k + 1)
9
+ end.reduce(:+)
13
10
  end
11
+
12
+ memoize :bernoulli
14
13
  end
data/lib/numb/catalan.rb CHANGED
@@ -4,10 +4,6 @@ class Integer
4
4
  end
5
5
 
6
6
  def catalan?
7
- n = -1
8
- loop do
9
- return true if (cat = (n += 1).catalan) == self
10
- return false if cat > self
11
- end
7
+ in_sequence?(seq: :catalan)
12
8
  end
13
9
  end
@@ -0,0 +1,58 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ # An abundant number is a number n for which σ(n) > 2n. That is, the sum of
4
+ # its divisors exceeds 2n. (See Integer#σ to compute the sum of the divisors
5
+ # of an arbitrary integer).
6
+ #
7
+ # Returns true if the number is abundant; false otherwise. Aliased to
8
+ # Integer#excessive?.
9
+ #
10
+ # 96.abundant? #=> true
11
+ # 100.abundant? #=> true
12
+ # 345.abundant? #=> false
13
+ #
14
+ def abundant?
15
+ return false unless positive?
16
+ σ > (2 * self)
17
+ end
18
+
19
+ alias :excessive? :abundant?
20
+
21
+ def abundancy
22
+ Rational(σ, self)
23
+ end
24
+
25
+ memoize :abundancy
26
+
27
+ def friendly?(*others)
28
+ raise ArgumentError unless others.size >= 1 && others.uniq.size == others.size
29
+ abundancy = self.abundancy
30
+ others.all? {|o| o.abundancy == abundancy}
31
+ end
32
+
33
+ def highly_abundant?
34
+ return true if self == 1
35
+ (self - 1).downto(1).all?{|m| σ > m.σ }
36
+ end
37
+
38
+ def primitive_abundant?
39
+ abundant? and proper_divisors.all?(&:deficient?)
40
+ end
41
+
42
+ def superabundant?
43
+ return true if self == 1
44
+ # Constraints due to "Abundant Numbers and the Riemann Hypothesis",
45
+ # Briggs, 2006, Experimental Mathematics, vol. 15, no. 2
46
+ ex = primaries.map(&:last)
47
+ return false unless [ex.last, ex.first] == ex.minmax
48
+ primaries[1..-1].all? do |b, e|
49
+ (e - (ex[0] * Math.log(b, primaries[0][0])).floor <= 1) and e < 2**(ex[0] + 2)
50
+ end or return false
51
+ return false unless [4, 36].include?(self) or ex.last == 1
52
+ 1.upto(self - 1).all? do |m|
53
+ m.abundancy < abundancy
54
+ end
55
+ end
56
+ memoize :superabundant?
57
+ end
58
+
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def aliquot_sequence(max_iterations=(self > 100 ? 10 : sqrt),
4
+ summatory_function=->(n){ n.aliquot_sum })
5
+ sequence = [self]
6
+ max_iterations.floor.times do |limit|
7
+ sequence << summatory_function[sequence.last]
8
+ break if sequence[0..-2].include?(sequence.last)
9
+ return sequence << (1/0.0) if limit.consecutive?(max_iterations)
10
+ end
11
+ sequence
12
+ end
13
+
14
+ def sociable?(t)
15
+ return false unless t >= 3
16
+ aliquot_sequence(t.succ).last == self
17
+ end
18
+
19
+ def unitary_sociable?(t)
20
+ return false unless t >= 3
21
+ seq = aliquot_sequence(t.succ, ->(n){ n.sum_of_unitary_divisors - n})
22
+ seq.size - 1 == t and seq.last == self
23
+ end
24
+
25
+ def aspiring?(max_iterations=10)
26
+ return false if perfect?
27
+ (last = aliquot_sequence(max_iterations).last).to_f.finite? ?
28
+ last.perfect? :
29
+ false
30
+ end
31
+ end
@@ -0,0 +1,38 @@
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
+
8
+ def amicable?(other)
9
+ n, m = [self, other].minmax
10
+ m.multiamicable?(n, 1, 1)
11
+ end
12
+
13
+ def augmented_amicable?(n)
14
+ m = self
15
+ [m.σ, n.σ].all?{|sigma| sigma == m + n - 1}
16
+ end
17
+
18
+ def betrothed?(m)
19
+ σ == m.σ and consecutive?(σ - m)
20
+ end
21
+
22
+ alias :quasi_amicable? :betrothed?
23
+ alias :reduced_amicable? :betrothed?
24
+
25
+ def breeder?(b)
26
+ a = self
27
+ x = (a.σ - a).fdiv(b)
28
+ abx = a + (b*x)
29
+ (abx == a.σ) and (abx == b.σ * (x + 1))
30
+ end
31
+
32
+ def unitary_amicable?(n)
33
+ [n + self, sum_of_unitary_divisors].all? do |other|
34
+ other == n.sum_of_unitary_divisors
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,73 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def k_perfect?(k)
4
+ σ == k * self
5
+ end
6
+
7
+ alias :multiply_perfect? :k_perfect?
8
+
9
+ def perfect?
10
+ return false if self < 6 or self.odd? or self.to_s !~ /(6|8)$/
11
+ return false if self != 6 and digital_root != 1
12
+ k_perfect?(2)
13
+ end
14
+
15
+ def semiperfect?
16
+ return false if deficient?
17
+ return true if perfect?
18
+ possibles = { 0 => true}
19
+ proper_sod = (sod = σ || 0) - self
20
+ proper_divisors.reverse.each do |divisor|
21
+ possibles.keys.each do |possible|
22
+ possibles.delete(possible) if possible + sod < self
23
+ x = possible + divisor
24
+ return true if x == self or x == proper_sod
25
+ possibles[x] = true if x < self
26
+ end
27
+ sod -= divisor
28
+ end
29
+ false
30
+ end
31
+
32
+ alias :pseudoperfect? :semiperfect?
33
+
34
+ def almost_perfect?
35
+ return true if self == 1
36
+ proper_divisors.reduce(:+) == self - 1
37
+ end
38
+
39
+ alias :least_deficient? :almost_perfect?
40
+ alias :slightly_defective? :almost_perfect?
41
+
42
+ def e_perfect?
43
+ return false if odd?
44
+ σe == 2 * self
45
+ end
46
+
47
+ def unitary_perfect?
48
+ proper_divisors.select do |divisor|
49
+ unitary_divisor?(divisor)
50
+ end.reduce(:+) == self
51
+ end
52
+
53
+ def hyperperfect?(k=1)
54
+ raise ArgumentError unless k >= 1
55
+ (1 + (k * (σ - self - 1))) == self
56
+ end
57
+
58
+ def superperfect?
59
+ σ.σ == 2 * self
60
+ end
61
+
62
+ def sublime?
63
+ number_of_divisors.perfect? and σ.perfect?
64
+ end
65
+
66
+ def primitive_pseudoperfect?
67
+ pseudoperfect? and proper_divisors.sort.none?(&:pseudoperfect?)
68
+ end
69
+
70
+ def infinitary_perfect?
71
+ σ∞ == 2*self
72
+ end
73
+ end
@@ -0,0 +1,389 @@
1
+ # coding: utf-8
2
+ class Integer
3
+ def weird?
4
+ return false unless positive?
5
+ return false if odd? && self < (10 ** 17)
6
+ not semiperfect? and abundant?
7
+ end
8
+
9
+ def unusual?
10
+ prime_factors.max > sqrt
11
+ end
12
+
13
+ def untouchable?
14
+ # * The first untouchable integer is 2
15
+ # * Perfect numbers are never untouchable because they can be expressed
16
+ # as the sum of their own proper divisors
17
+ # * If p is prime, the sum of the proper divisors of p**2 is p + 1;
18
+ # therefore, no untouchable number is one more than a prime.
19
+ return false if self < 2 or perfect? or (self - 1).prime?
20
+ (1..((self - 1)**2)).none? do |m|
21
+ m.σ - m == self
22
+ end
23
+ end
24
+
25
+ def unitary_divisor?(x)
26
+ x.coprime?(self/x)
27
+ end
28
+
29
+ def powerful?
30
+ return false unless positive?
31
+ divisors = self.divisors
32
+ divisors.select {|d| d.prime? }.all?{|prime| divisors.include? (prime ** 2)}
33
+ end
34
+
35
+ alias :handsome? :powerful?
36
+
37
+ # An Achilles number is powerful but not a perfect power.
38
+ #
39
+ # Returns true if self is an Achilles number; false otherwise.
40
+ #
41
+ # 1152.achilles? #=> true
42
+ # 4563.achilles? #=> true
43
+ # 100.achilles? #=> false
44
+ #
45
+ def achilles?
46
+ powerful? and not perfect_power?
47
+ end
48
+
49
+ def perfect_power?
50
+ return false unless positive?
51
+ return true if self == 1
52
+ divisors = self.divisors
53
+ (2..Math.log2(self)).any? { |pow| divisors.any? {|div| (div ** pow) == self} }
54
+ end
55
+
56
+ def brilliant?
57
+ pfacts = prime_factors
58
+ pfacts.size == 2 and pfacts.map{|f| f.to_s.size}.uniq.size == 1
59
+ end
60
+
61
+ def coprime?(x)
62
+ gcd(x) == 1
63
+ end
64
+
65
+ alias :⊥ :coprime?
66
+ alias :stranger? :coprime?
67
+
68
+ # A deficient number is a number n for which σ(n) < 2n. That is, the sum of
69
+ # its divisors are less than the number. (To calculate the sum of divisors
70
+ # for an arbitrary integer see Integer#σ).
71
+ #
72
+ # Returns true if the number is deficient; false otherwise.
73
+ #
74
+ # 8.deficient? #=> true
75
+ # 27.deficient? #=> true
76
+ # 6.deficient? #=> false
77
+ #
78
+ def deficient?
79
+ return false unless positive?
80
+ σ < (2 * self)
81
+ end
82
+
83
+ alias :defective? :deficient?
84
+
85
+ def e_divisors
86
+ return [1] if self == 1
87
+ pfacts = primaries
88
+ comb = pfacts.map{|p,a| (1..a).select{|b| a.divides?(b)}.map{|b| p**b}}
89
+ comb.flatten.permutation(pfacts.size).select do |perm|
90
+ perm.each_with_index.all?{|x,i| comb[i].include? x}
91
+ end.map{|perm| perm.reduce(:*)}
92
+ end
93
+
94
+ # An extravagant number has fewer digits than the number of digits in its
95
+ # prime factorization (including exponents).
96
+ #
97
+ # Returns true if self is extravagant; false otherwise. Aliased to
98
+ # Integer#wasteful?.
99
+ #
100
+ # 234.extravagant? #=> true
101
+ # 87.extravagant? #=> true
102
+ # 81.extravagant? #=> false
103
+ #
104
+ def extravagant?
105
+ digits.size < prime_division.flatten.reject{|d|d==1}.join.to_i.digits.size
106
+ end
107
+
108
+ alias :wasteful? :extravagant?
109
+
110
+ def politeness
111
+ divisors.select{|d| d > 1}.select{|d| d.odd?}.size
112
+ end
113
+
114
+ def impolite?
115
+ not polite?
116
+ end
117
+
118
+ def polite?
119
+ return true if self == 1
120
+ politeness.positive?
121
+ end
122
+
123
+ def proper_divisors
124
+ divisors.reject {|d| d == self }
125
+ end
126
+
127
+ def divisors
128
+ return [] unless positive?
129
+ return [1, self] if prime?
130
+ (1..isqrt).select { |n| (self % n).zero? }.
131
+ map {|n| [n, self/n]}.flatten.uniq
132
+ end
133
+ memoize :divisors
134
+
135
+ def sum_of_divisors
136
+ @sod ||= divisors.reduce(:+)
137
+ end
138
+ alias :σ :sum_of_divisors
139
+
140
+ def aliquot_sum
141
+ return 0 if zero?
142
+ σ - self
143
+ end
144
+
145
+ def divides?(n)
146
+ not n.zero? and (self % n).zero?
147
+ end
148
+
149
+ def σe
150
+ # TODO: If squarefree, the sum of a number’s e-divisors is the number
151
+ # itself. Do we gain anything significant by special-casing this?
152
+ e_divisors.reduce(:+)
153
+ end
154
+
155
+ alias :sum_of_e_divisors :σe
156
+
157
+ def σ∞
158
+ infinitary_divisors.reduce :+
159
+ end
160
+
161
+ alias :sum_of_infinitary_divisors :σ∞
162
+ alias :isigma :σ∞
163
+
164
+ def sum_of_unitary_divisors
165
+ divisors.select{|d| unitary_divisor?(d)}.reduce(:+) or 0
166
+ end
167
+
168
+ def highly_composite?
169
+ return false if self > 6 and not (abundant? or primorial_product?)
170
+ return true if [1,4,36].include?(self)
171
+ minimal? and (self - 1).downto(1).all?{|n| τ > n.τ}
172
+ end
173
+
174
+ alias :julian? :highly_composite?
175
+
176
+ def d?
177
+ knödel?(3)
178
+ end
179
+
180
+ # A number which is either frugal or equidigital.
181
+ #
182
+ # Returns true if self is economical; false otherwise.
183
+ #
184
+ # See also Integer#equidigital? and Integer#frugal?.
185
+ #
186
+ # 243.economical? #=> true
187
+ # 7.economical? #=> true
188
+ # 989.economical? #=> false
189
+ #
190
+ def economical?
191
+ equidigital? or frugal?
192
+ end
193
+
194
+ # An equidigital number has the same number of digits as
195
+ # the number of digits in its prime factorization (including exponents).
196
+ #
197
+ # For example, 35 is equidigital because it has two digits and two 1-digit
198
+ # prime factors (5 and 7).
199
+ #
200
+ # Returns true if self is equidigital; false otherwise.
201
+ #
202
+ # 81.equidigital? #=> true
203
+ # 49.equidigital? #=> true
204
+ # 1287.equidigital? #=> false
205
+ #
206
+ def equidigital?
207
+ digits.size == prime_division.flatten.reject{|d|d==1}.join.to_i.digits.size
208
+ end
209
+
210
+ def giuga?
211
+ composite? and prime_factors.uniq.all? do |p|
212
+ ((self / p) - 1).divides?(p)
213
+ end
214
+ end
215
+
216
+ def harshad?
217
+ self >= 1 and (self % digital_sum).zero?
218
+ end
219
+
220
+ alias :niven? :harshad?
221
+ alias :multidigital? :harshad?
222
+
223
+ def hoax?
224
+ return false unless composite?
225
+ sum_of_digits == prime_factors.uniq.map{|f| f.sum_of_digits}.reduce(:+)
226
+ end
227
+
228
+ def infinitary_divisors
229
+ pf = Hash[prime_factors.uniq.map{|f| [f, 0]}]
230
+ bin = divisors.map do |d|
231
+ prime_divisors = pf.map(&:first)
232
+ [d, pf.merge(Hash[d.primaries]).
233
+ values.
234
+ map{|v| sprintf("%.#{to_s(2).size}b", v)}.join]
235
+ end
236
+ bin = Hash[bin]
237
+ target = bin[self].chars.map.with_index.to_a.select{|a,b| a == '0'}.map(&:last)
238
+ bin.select{|d,b| target.all?{|i| b[i] == '0'}}.keys.sort
239
+ end
240
+
241
+ def ore?
242
+ div = divisors
243
+ Rational(div.size, div.map{|d| Rational(1, d)}.reduce(:+)).denominator == 1
244
+ end
245
+
246
+ alias :harmonic_divisor? :ore?
247
+
248
+ # Implementation of Stewart, B. M. (1954), "Sums of distinct divisors",
249
+ # American Journal of Mathematics 76: 779–785, doi:10.2307/2372651,
250
+ # MR0064800
251
+ def practical?
252
+ sum = 1
253
+ k = 2
254
+ n = self
255
+ while (n >= k)
256
+ s = 1
257
+ u = 0
258
+ while (n % k == 0)
259
+ n = n/k
260
+ s = s * k + 1
261
+ u += 1
262
+ end
263
+ unless (u == 0)
264
+ return false if (k > sum + 1)
265
+ sum *= s
266
+ end
267
+ k += (k == 2) ? 1 : 2
268
+ end
269
+ true
270
+ end
271
+
272
+ def rhonda?(base=10)
273
+ d = base == 10 ? digits : to_s(base).split(//).map{|_| _.to_i(base)}
274
+ d.reduce(:*) == base * (prime_factors.reduce(:+) || 0)
275
+ end
276
+
277
+ def smith?
278
+ return false if prime?
279
+ digital_sum == prime_division.map{|d,e| d.digital_sum * e}.reduce(:+)
280
+ end
281
+
282
+ def smooth?(b)
283
+ prime_factors.none?{|f| f > b}
284
+ end
285
+
286
+ def rough?(k)
287
+ prime_factors.all?{|f| f >= k}
288
+ end
289
+
290
+ def super_poulet?
291
+ poulet? and divisors.all?{|d| ((2**d) - 2).divides?(d)}
292
+ end
293
+
294
+ # Algorithm derived from Formulas for pi(n) and the n-th prime by Sebastian
295
+ # Martin Ruiz and Jonathan Sondow [arXiv:math/0210312v2 [math.NT]]
296
+
297
+ # Returns the number of divisors of self
298
+ def τ
299
+ # TODO: Consider something simpler, and perhaps faster, like
300
+ # primaries.map(&:last).map(&:succ).reduce(:*)
301
+ n = self
302
+ return @nod if defined?(@nod)
303
+ @nod = (1..isqrt).
304
+ map {|i| n.quo(i).to_i - (n - 1).quo(i).to_i }.
305
+ reduce(:+) * 2
306
+ @nod -= 1 if square?
307
+ @nod
308
+ end
309
+
310
+ alias :number_of_divisors :τ
311
+ alias :d :τ
312
+ memoize :τ
313
+
314
+ def perfect_power
315
+ return 1 if (n = self) <= 1
316
+ this = (n - 1).perfect_power.succ
317
+ this += 1 while (this.prime? or not this.perfect_power?)
318
+ this
319
+ end
320
+ memoize :perfect_power
321
+
322
+ def first_with_n_divisors
323
+ if zero? then 0
324
+ elsif self == 1 then 1
325
+ elsif not positive? then nil
326
+ else
327
+ pf = prime_factors
328
+ if pf.uniq == [2]
329
+ list = []
330
+ Prime.each do |prime|
331
+ break if prime > self
332
+ list << prime
333
+ exp = 1
334
+ loop do
335
+ pow2 = 2 ** exp
336
+ break if pow2 > self
337
+ prime **= pow2
338
+ break if prime > self
339
+ list << prime
340
+ end
341
+ end
342
+ list.sort.uniq.first(pf.size).reduce(:*)
343
+ else
344
+ limit = Prime.first(pf.size).zip(pf.reverse).map{|b,e| b**(e-1)}.reduce(:*)
345
+ neighbour = ->(e) { (self/e).divisors.reject{|d| d > e} }
346
+ x, div, exponents = self, divisors, {}
347
+
348
+ # TODO: Consider using limit's primaries as an upper limit on the
349
+ # exponents
350
+ Prime.each do |b|
351
+ max_exponent = Math.log(limit, b).floor
352
+ d = div.reject{|d| d > max_exponent}.sort.reverse - [1]
353
+ unless b == 2
354
+ prev_neighbours = exponents[exponents.keys.last].values.flatten
355
+ d.reject!{|e, n| not prev_neighbours.include?(e)}
356
+ end
357
+ exponents[b] = Hash[d.map{|e| [e, neighbour.(e)]}]
358
+ break if (x /= b) < 1
359
+ end
360
+
361
+ complete_chain = ->(b, e, goal=self, chain=nil) do
362
+ chain ||= {chain: [[b, e]]}
363
+ return chain unless exponents.key?(b) and exponents[b].key?(e)
364
+ exponents[b][e].map do |n|
365
+ this = {chain: chain[:chain].dup}
366
+ this[:chain].pop if this[:chain].last.first == b.next_prime
367
+ this[:chain] << [b.next_prime, n]
368
+ e * n < goal ? complete_chain[b.next_prime, n, goal/e, this] : this
369
+ end
370
+ end
371
+
372
+ exponents[2].keys.map do |e,|
373
+ complete_chain[2, e].flatten.map{|c| Hash[c[:chain]]}.
374
+ select{|c| c.values.reduce(:*) == self}.
375
+ map{|c| c.map{|b,e| b**(e-1)}.reduce(:*)}.
376
+ reject{|prod| prod > limit}
377
+ end.flatten.min or limit
378
+ end
379
+ end
380
+ end
381
+
382
+ def minimal?
383
+ τ.first_with_n_divisors == self
384
+ end
385
+
386
+ def square_part
387
+ divisors.sort.reverse.each{|d| return d if d.square?}
388
+ end
389
+ end
@@ -5,5 +5,7 @@ class Integer
5
5
  return 0 if (self < k or k < 0)
6
6
  entringer(k - 1) + (self - 1).entringer(self - k)
7
7
  end
8
+
9
+ memoize :entringer
8
10
  end
9
11