numb 0.152.0 → 0.170.0

Sign up to get free protection for your applications and to get access to all the features.
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