-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPerfectNumbersCalculator.js
97 lines (90 loc) · 2.85 KB
/
PerfectNumbersCalculator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
This class acts as a utility to find perfect number values
*/
class PerfectNumbersCalculator {
constructor(config) {
this.setNewMaximum(config);
}
getNonPrimesBelow(max) {
const gen = this._generatePrimes(false);
let curCount = 4;
const integerArr = []; // Only add non-primes to this array
while (curCount <= max) {
curCount = gen.next().value;
integerArr.push(curCount);
}
integerArr.pop();
return integerArr;
}
* _generatePrimes(getPrimes = true) { // False generates non-primes array
const markedNotPrimeMap = new Map();
let valueToCheck = 2;
while(true) {
if (!(markedNotPrimeMap.has(valueToCheck))) {
if (getPrimes) yield valueToCheck
markedNotPrimeMap.set(valueToCheck**2, [valueToCheck])
} else {
let primes =markedNotPrimeMap.get(valueToCheck)
primes.forEach(prime=> {
let nextMultipleOfPrime = prime + valueToCheck;
if (markedNotPrimeMap.has(nextMultipleOfPrime)) {
markedNotPrimeMap.get(nextMultipleOfPrime).push(prime);
} else {
markedNotPrimeMap.set(nextMultipleOfPrime, [prime]);
}
})
markedNotPrimeMap.delete(valueToCheck);
if (!getPrimes) yield valueToCheck
}
valueToCheck += 1
}
}
setNewMaximum({ max }) {
this.max = max;
console.log(`Maximum number set to ${max}`);
this.integerArr = this.getNonPrimesBelow(max);
}
_getTimeDiff(startTime) {
const timeNow = new Date();
return ((timeNow - startTime) / 1000).toFixed(2);
}
checkIfPerfect(num, log = true) {
const divisors = this.getDivisors(num)
const sum = divisors.reduce(
((total, currentValue) => total + currentValue), 0
);
if (sum === num) {
if (log) console.log(`Number ${num} is perfect!`);
return true;
}
if (log) console.log(`Number ${num} is not perfect.`);
return false;
}
getDivisors(num) {
let count = 1;
const divisors = [];
while(count < num) {
if (Number.isInteger(num / count)) divisors.push(count);
count++;
if(count > num/2) break; // Over half is not a divisor
}
return divisors;
}
findPerfects() {
const startTime = new Date();
const perfectNums = []; // Store results in an array
this.integerArr.forEach(number => {
if (number % (this.max / 100) === 0) {
console.log(
`On number ${number}. ${100*number / this.max}% done.`
+ ` Time taken: ${this._getTimeDiff(startTime)}s`
);
}
const perf = this.checkIfPerfect(number, false);
if (perf) perfectNums.push(number);
});
// Print the results
console.log(`100% done in ${this._getTimeDiff(startTime)}s.`
+ ` Result: [${perfectNums. join(', ')}].`);
}
};