Perfect::rewind()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace drupol\phpermutations\Iterators;
6
7
use drupol\phpermutations\Iterators;
8
9
use const PHP_INT_MAX;
10
11
class Perfect extends Iterators
12
{
13
    /**
14
     * The maximum limit.
15
     *
16
     * @var int
17
     */
18
    protected $max;
19
20
    /**
21
     * The minimum limit.
22
     *
23
     * @var int
24
     */
25
    protected $min;
26
27
    /**
28
     * Perfect constructor.
29
     */
30 2
    public function __construct()
31
    {
32 2
        $this->setMaxLimit(PHP_INT_MAX);
33 2
        $this->setMinLimit(2);
34 2
        parent::__construct([], null);
35 2
    }
36
37
    /**
38
     * {@inheritdoc}
39
     */
40 2
    public function current(): mixed
41
    {
42 2
        for ($i = $this->key(); $this->getMaxLimit() > $i; ++$i) {
43 2
            if ($this->isPerfectNumber($i)) {
44 2
                $this->key = $i;
45
46 2
                return $i;
47
            }
48
        }
49
50 2
        return $this->getMaxLimit();
51
    }
52
53
    /**
54
     * Get the maximum limit.
55
     *
56
     * @return int
57
     *             The limit
58
     */
59 2
    public function getMaxLimit(): int
60
    {
61 2
        return (int) $this->max;
62
    }
63
64
    /**
65
     * Get the minimum limit.
66
     *
67
     * @return int
68
     *             The limit
69
     */
70 2
    public function getMinLimit(): int
71
    {
72 2
        return 2 > $this->min ? 2 : $this->min;
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     *
78
     * @return void
79
     */
80 2
    public function next(): void
81
    {
82 2
        ++$this->key;
83 2
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88 2
    public function rewind(): void
89
    {
90 2
        $this->key = $this->getMinLimit();
91 2
    }
92
93
    /**
94
     * Set the maximum limit.
95
     *
96
     * @param int $max
97
     *                 The limit
98
     *
99
     * @return void
100
     */
101 2
    public function setMaxLimit($max): void
102
    {
103 2
        $this->max = $max;
104 2
    }
105
106
    /**
107
     * Set the minimum limit.
108
     *
109
     * @param int $min
110
     *                 The limit
111
     *
112
     * @return void
113
     */
114 2
    public function setMinLimit($min): void
115
    {
116 2
        $this->min = $min;
117 2
    }
118
119
    /**
120
     * {@inheritdoc}
121
     *
122
     * @return bool
123
     */
124 2
    public function valid(): bool
125
    {
126 2
        return $this->current() < $this->getMaxLimit();
127
    }
128
129
    /**
130
     * Test if a number is perfect or not.
131
     *
132
     * Source: http://iceyboard.no-ip.org/projects/code/php/perfect_number/
133
     *
134
     * @param int $number
135
     *                    The number to test
136
     *
137
     * @return bool
138
     *              The true if the number is perfect, false otherwise
139
     */
140 2
    protected function isPerfectNumber($number): bool
141
    {
142 2
        $d = 0;
143 2
        $max = sqrt($number);
144
145 2
        for ($n = 2; $n <= $max; ++$n) {
146 2
            if (!($number % $n)) {
147 2
                $d += $n;
148
149 2
                if ($number / $n !== $n) {
150 2
                    $d += $number / $n;
151
                }
152
            }
153
        }
154
155 2
        return ++$d === $number;
156
    }
157
}
158