numb 0.185.0 → 0.186.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.185.0
1
+ 0.186.0
@@ -33,6 +33,9 @@ class Integer
33
33
 
34
34
  def almost_perfect?
35
35
  return true if self == 1
36
+ # TODO: All known almost perfect numbers are powers of 2. If self
37
+ # is within the range of integers thus tested, a power_of?(2) test
38
+ # would avoid the need to factorise.
36
39
  proper_divisors.reduce(:+) == self - 1
37
40
  end
38
41
 
data/lib/numb/totient.rb CHANGED
@@ -7,4 +7,38 @@ class Integer
7
7
  end
8
8
 
9
9
  alias :totient :φ
10
+
11
+
12
+ # Returns `true` if `self` is equal to the sum of its iterated
13
+ # totients, otherwise `false`
14
+ #
15
+ # For example: φ(183) = 120
16
+ # φ(120) = 32
17
+ # φ(32) = 16
18
+ # φ(16) = 8
19
+ # φ(4) = 2
20
+ # φ(2) = 1
21
+ # 120 + 32 + 16 + 8 + 4 + 2 + 1 = 183
22
+ # @return [true, false] `true` if `self` is a perfect totient; `false` otherwise.
23
+ def perfect_totient?
24
+ # TODO: Possible optimisation: once the totient is a power of 2,
25
+ # which we identify using bit ops, it is predictable what totients
26
+ # will follow. For example, consider 441027. Its iterated totients
27
+ # are [294012, 97992, 32640, 8192, 4096, 2048, 1024, 512, 256,
28
+ # 128, 64, 32, 16, 8, 4, 2, 1], i.e. 17 iterations are
29
+ # needed. Once we hit 8192, we can derive [2, 4, 8, 16, 32, 64,
30
+ # 128, 256, 512, 1024, 2048, 4096, 8192], add the 1, then return.
31
+
32
+ # TODO: The more obvious tweak is to return true immediately when
33
+ # self is a power of 3. I want to write a #power_of? predicate for
34
+ # the general case first, then benchmark it for use here.
35
+ return false if even?
36
+ a = [totient]
37
+ sum = a.first
38
+ until a.last == 1 or sum > self
39
+ a << a.last.totient
40
+ sum += a.last
41
+ end
42
+ sum == self
43
+ end
10
44
  end
@@ -0,0 +1,30 @@
1
+ describe Integer, "#perfect_totient?" do
2
+ # A082897
3
+ @seq = [3,9,15,27,39,81,111,183,243,255,327,363,471,729,
4
+ 2187,2199,3063,4359,4375,5571,6561,8751,15723,
5
+ 19683,36759,46791,59049,65535,140103,177147,
6
+ 208191,441027,531441,1594323,4190263,4782969,
7
+ 9056583,14348907,43046721] |
8
+ # A091847
9
+ [15,39,111,183,255,327,363,471,2199,3063,4359,
10
+ 4375,5571,8751,15723,36759,46791,65535,140103,
11
+ 208191,441027,4190263,9056583,57395631,172186887,
12
+ 236923383,918330183,3932935775,4294967295,
13
+ 4764161215]
14
+
15
+ @seq.each do |n|
16
+ it "returns true for perfect totient number #{n}" do
17
+ n.should be_perfect_totient
18
+ end
19
+
20
+ m = n + 2
21
+ it "returns false for non-perfect-totient number #{m}" do
22
+ m.should_not be_perfect_totient
23
+ end
24
+
25
+ m += 1
26
+ it "returns false for even number #{m}" do
27
+ m.should_not be_perfect_totient
28
+ end
29
+ end
30
+ end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 185
7
+ - 186
8
8
  - 0
9
- version: 0.185.0
9
+ version: 0.186.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Run Paint Run Run
@@ -343,6 +343,7 @@ files:
343
343
  - spec/numb/pentatope_spec.rb
344
344
  - spec/numb/perfect_power_spec.rb
345
345
  - spec/numb/perfect_spec.rb
346
+ - spec/numb/perfect_totient_spec.rb
346
347
  - spec/numb/perrin_spec.rb
347
348
  - spec/numb/persistent_spec.rb
348
349
  - spec/numb/polite_spec.rb
@@ -493,6 +494,7 @@ test_files:
493
494
  - spec/numb/emrip_spec.rb
494
495
  - spec/numb/minimal_spec.rb
495
496
  - spec/numb/weird_spec.rb
497
+ - spec/numb/perfect_totient_spec.rb
496
498
  - spec/numb/practical_spec.rb
497
499
  - spec/numb/ore_spec.rb
498
500
  - spec/numb/base_spec.rb