1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace drupol\phpermutations\Iterators; |
4
|
|
|
|
5
|
|
|
use drupol\phpermutations\Combinatorics; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* Class Perfect. |
9
|
|
|
* |
10
|
|
|
* @package drupol\phpermutations\Iterators |
11
|
|
|
*/ |
12
|
|
|
class Perfect extends Combinatorics implements \Iterator, \Countable { |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* The maximum limit. |
16
|
|
|
* |
17
|
|
|
* @var int |
18
|
|
|
*/ |
19
|
|
|
protected $max; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* The key. |
23
|
|
|
* |
24
|
|
|
* @var int |
25
|
|
|
*/ |
26
|
|
|
protected $key; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* The count. |
30
|
|
|
* |
31
|
|
|
* @var int |
32
|
|
|
*/ |
33
|
|
|
protected $count = 1; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* The default current value. |
37
|
|
|
* |
38
|
|
|
* @var int |
39
|
|
|
*/ |
40
|
|
|
protected $current = 2; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Perfect constructor. |
44
|
|
|
*/ |
45
|
2 |
|
public function __construct() { |
46
|
2 |
|
$this->setMaxLimit(PHP_INT_MAX); |
47
|
2 |
|
} |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* {@inheritdoc} |
51
|
|
|
*/ |
52
|
2 |
|
public function current() { |
53
|
2 |
|
return $this->current; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* {@inheritdoc} |
58
|
|
|
*/ |
59
|
2 |
View Code Duplication |
public function next() { |
|
|
|
|
60
|
2 |
|
++$this->key; |
61
|
2 |
|
for ($i = $this->key; $i < $this->getMaxLimit(); $i++) { |
62
|
2 |
|
if ($this->isPerfectNumber($i)) { |
63
|
2 |
|
$this->key = $i; |
64
|
2 |
|
$this->current = $i; |
65
|
2 |
|
$this->count++; |
66
|
2 |
|
break; |
67
|
|
|
} |
68
|
2 |
|
} |
69
|
2 |
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* {@inheritdoc} |
73
|
|
|
*/ |
74
|
2 |
|
public function key() { |
75
|
2 |
|
return $this->key; |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* {@inheritdoc} |
80
|
|
|
*/ |
81
|
2 |
|
public function valid() { |
82
|
2 |
|
return ($this->current == $this->key()); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* {@inheritdoc} |
87
|
|
|
*/ |
88
|
2 |
|
public function rewind() { |
89
|
2 |
|
$this->key = 2; |
90
|
2 |
|
$this->current = 2; |
91
|
2 |
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Count elements of an object. |
95
|
|
|
* |
96
|
|
|
* @return int |
97
|
|
|
* The number of element. |
98
|
|
|
*/ |
99
|
2 |
|
public function count() { |
100
|
2 |
|
return count($this->toArray()); |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Convert the iterator into an array. |
105
|
|
|
* |
106
|
|
|
* @return array |
107
|
|
|
* The elements. |
108
|
|
|
*/ |
109
|
2 |
|
public function toArray() { |
110
|
2 |
|
$data = array(); |
111
|
|
|
|
112
|
2 |
|
for ($this->rewind(); $this->valid(); $this->next()) { |
113
|
2 |
|
$data[] = $this->current(); |
114
|
2 |
|
} |
115
|
|
|
|
116
|
2 |
|
return $data; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* Test if a number is perfect or not. |
121
|
|
|
* |
122
|
|
|
* Source: http://iceyboard.no-ip.org/projects/code/php/perfect_number/ |
123
|
|
|
* |
124
|
|
|
* @param int $number |
125
|
|
|
* The number to test. |
126
|
|
|
* |
127
|
|
|
* @return bool |
128
|
|
|
* The true if the number is perfect, false otherwise. |
129
|
|
|
*/ |
130
|
2 |
|
protected function isPerfectNumber($number) { |
131
|
2 |
|
$d = 0; |
|
|
|
|
132
|
2 |
|
$max = sqrt($number); |
133
|
2 |
|
for ($n = 2; $n <= $max; $n++) { |
134
|
2 |
|
if (!($number % $n)) { |
135
|
2 |
|
$d += $n; |
136
|
2 |
|
if ($n <> $number / $n) { |
137
|
2 |
|
$d += $number / $n; |
138
|
2 |
|
} |
139
|
2 |
|
} |
140
|
2 |
|
} |
141
|
|
|
|
142
|
2 |
|
return ++$d == $number; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Set the maximum limit. |
147
|
|
|
* |
148
|
|
|
* @param int $max |
149
|
|
|
* The limit. |
150
|
|
|
*/ |
151
|
2 |
|
public function setMaxLimit($max) { |
152
|
2 |
|
$this->max = $max; |
153
|
2 |
|
} |
154
|
|
|
|
155
|
|
|
/** |
156
|
|
|
* Get the maximum limit. |
157
|
|
|
* |
158
|
|
|
* @return int |
159
|
|
|
* The limit. |
160
|
|
|
*/ |
161
|
2 |
|
public function getMaxLimit() { |
162
|
2 |
|
return intval($this->max); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
} |
166
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.