|
|
@@ -1,68 +1,39 @@
|
|
|
-export class Prime {
|
|
|
- private static values: number[] = [2, 3, 5, 7];
|
|
|
-
|
|
|
- private static lastKnown(): number {
|
|
|
- return Prime.values.slice(-1)[0];
|
|
|
- }
|
|
|
-
|
|
|
- private static searchNextKnownPrime(
|
|
|
- number: number,
|
|
|
- from = 0,
|
|
|
- to: number = Prime.values.length,
|
|
|
- ): number {
|
|
|
- if (0 > number || number >= Prime.lastKnown()) {
|
|
|
- throw new Error("we are wandering in unknown realms...");
|
|
|
- }
|
|
|
-
|
|
|
- // this is a binary search
|
|
|
- // basically we are splitting the list into two halves and
|
|
|
- // then discard the half that does not contain the input number
|
|
|
- // and call the function again with the remaining half
|
|
|
- // but instead of always compiling a new array we just use indices of base array
|
|
|
-
|
|
|
- const length = to - from;
|
|
|
+import { OrderedUniqueNumbers } from "./ordered-unique-numbers.class.ts";
|
|
|
|
|
|
- if (length > 1) {
|
|
|
- const middle = from + Math.floor(length / 2);
|
|
|
-
|
|
|
- return Prime.values[middle] > number
|
|
|
- ? Prime.searchNextKnownPrime(number, from, middle)
|
|
|
- : Prime.searchNextKnownPrime(number, middle + 1, to);
|
|
|
- }
|
|
|
-
|
|
|
- return Prime.values[from] > number
|
|
|
- ? Prime.values[from]
|
|
|
- : Prime.values[from + 1];
|
|
|
+export class Prime {
|
|
|
+ private static values: OrderedUniqueNumbers = new OrderedUniqueNumbers([
|
|
|
+ 2,
|
|
|
+ 3,
|
|
|
+ 5,
|
|
|
+ 7,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ private static get lastKnown(): number {
|
|
|
+ return Prime.values.max;
|
|
|
}
|
|
|
|
|
|
- private static findNextUnknown(): number {
|
|
|
- let number = Prime.lastKnown();
|
|
|
+ private static get findNextUnknown(): number {
|
|
|
+ let number = Prime.lastKnown;
|
|
|
|
|
|
do {
|
|
|
number += 2;
|
|
|
} while (!Prime.isPrime(number));
|
|
|
|
|
|
- Prime.values.push(number);
|
|
|
+ Prime.values.add(number);
|
|
|
return number;
|
|
|
}
|
|
|
|
|
|
private static next(number: number): number {
|
|
|
- if (number < Prime.lastKnown()) {
|
|
|
- // if input is a prime number just return the next one in our list
|
|
|
- const index = Prime.values.indexOf(number);
|
|
|
- if (index !== -1) {
|
|
|
- return Prime.values[index + 1];
|
|
|
- }
|
|
|
-
|
|
|
+ if (number < Prime.lastKnown) {
|
|
|
// input is not a prime number, so we have to find the next larger entry
|
|
|
- return Prime.searchNextKnownPrime(number);
|
|
|
+ return Prime.values.findNextLargerValue(number);
|
|
|
}
|
|
|
|
|
|
// input is larger than last known prime number in our list
|
|
|
// so we need to brute force the next one
|
|
|
let next: number;
|
|
|
do {
|
|
|
- next = Prime.findNextUnknown();
|
|
|
+ next = Prime.findNextUnknown;
|
|
|
} while (next <= number);
|
|
|
return next;
|
|
|
}
|
|
|
@@ -72,14 +43,14 @@ export class Prime {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- if (number <= Prime.lastKnown()) {
|
|
|
- return Prime.values.indexOf(number) !== -1;
|
|
|
+ if (number <= Prime.lastKnown) {
|
|
|
+ return Prime.values.contains(number);
|
|
|
}
|
|
|
|
|
|
const limit = Math.sqrt(number);
|
|
|
|
|
|
- if (limit <= Prime.lastKnown()) {
|
|
|
- for (const prime of Prime.values) {
|
|
|
+ if (limit <= Prime.lastKnown) {
|
|
|
+ for (const prime of Prime.values.list) {
|
|
|
if (prime > limit) {
|
|
|
break;
|
|
|
}
|
|
|
@@ -92,7 +63,7 @@ export class Prime {
|
|
|
}
|
|
|
|
|
|
// calculate new prime numbers up to limit
|
|
|
- while (Prime.findNextUnknown() < limit);
|
|
|
+ while (Prime.findNextUnknown < limit);
|
|
|
|
|
|
// now we should have a sufficient list
|
|
|
// to determine if input is a prime number
|
|
|
@@ -104,10 +75,10 @@ export class Prime {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- const prev = Prime.values[Prime.values.indexOf(number) - 1];
|
|
|
- const next = Prime.lastKnown() === number
|
|
|
- ? Prime.findNextUnknown()
|
|
|
- : Prime.values[Prime.values.indexOf(number) + 1];
|
|
|
+ const prev = Prime.values.list[Prime.values.list.indexOf(number) - 1];
|
|
|
+ const next = Prime.lastKnown === number
|
|
|
+ ? Prime.findNextUnknown
|
|
|
+ : Prime.values.list[Prime.values.list.indexOf(number) + 1];
|
|
|
|
|
|
return Math.pow(number, 2) > prev * next;
|
|
|
}
|
|
|
@@ -118,10 +89,10 @@ export class Prime {
|
|
|
}
|
|
|
|
|
|
const square = Math.pow(number, 2);
|
|
|
- const pos = Prime.values.indexOf(number);
|
|
|
+ const pos = Prime.values.list.indexOf(number);
|
|
|
let upper = number;
|
|
|
for (let i = pos - 1; i >= 0; i -= 1) {
|
|
|
- const lower = Prime.values[i];
|
|
|
+ const lower = Prime.values.list[i];
|
|
|
upper = Prime.next(upper);
|
|
|
|
|
|
if (square < lower * upper) {
|
|
|
@@ -137,10 +108,10 @@ export class Prime {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- const prev = Prime.values[Prime.values.indexOf(number) - 1];
|
|
|
- const next = Prime.lastKnown() === number
|
|
|
- ? Prime.findNextUnknown()
|
|
|
- : Prime.values[Prime.values.indexOf(number) + 1];
|
|
|
+ const prev = Prime.values.list[Prime.values.list.indexOf(number) - 1];
|
|
|
+ const next = Prime.lastKnown === number
|
|
|
+ ? Prime.findNextUnknown
|
|
|
+ : Prime.values.list[Prime.values.list.indexOf(number) + 1];
|
|
|
|
|
|
return number === (prev + next) / 2;
|
|
|
}
|
|
|
@@ -225,8 +196,8 @@ export class Prime {
|
|
|
primes.forEach((a) => {
|
|
|
primes.forEach((b) => {
|
|
|
arr = arr.filter((n) => n !== a - b && n !== b - a);
|
|
|
- })
|
|
|
- })
|
|
|
+ });
|
|
|
+ });
|
|
|
|
|
|
return arr.length === 0;
|
|
|
}
|
|
|
@@ -240,9 +211,9 @@ export class Prime {
|
|
|
const outOfLimit = Prime.next(to);
|
|
|
|
|
|
// deliver the list of known primes up to (but excluding) retrieved prime
|
|
|
- return Prime.values.slice(
|
|
|
+ return Prime.values.list.slice(
|
|
|
0,
|
|
|
- Prime.values.indexOf(outOfLimit),
|
|
|
+ Prime.values.list.indexOf(outOfLimit),
|
|
|
);
|
|
|
}
|
|
|
}
|