Reputation: 56936
I have an array of prime numbers:
const primes = [3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
I want to find the first number in this list that is <= the number given.
For example ... getHighestPrimeNumber(58)
... should return 53, being the prime number with the greatest value which is also less than or equal to 58
Expect results:
getHighestPrimeNumber(58) === 53
getHighestPrimeNumber(53) === 53
getHighestPrimeNumber(52) === 47
My current approach is to iterate through the prime numbers but this is very inefficient, especially given that there may be 10,000+ numbers in the list - thanks
Vanilla JS or Lodash is fine
Upvotes: 2
Views: 164
Reputation: 18515
Since you posted this with lodash
tag just FYI that this with it is trivial due to _.sortedIndex:
const primes = [3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
const closestPrime = (n) => {
let index = _.sortedIndex(primes, n)
return primes[index] == n ? primes[index] : primes[index-1]
}
console.log(closestPrime(58))
console.log(closestPrime(53))
console.log(closestPrime(52))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Upvotes: 4
Reputation: 56865
This is a good task for a binary search:
const bisect = (needle, haystack) => {
let lo = 0;
let hi = haystack.length;
while (lo <= hi) {
const mid = ~~((hi - lo) / 2 + lo);
if (haystack[mid] === needle) {
return needle;
}
else if (haystack[mid] > needle) {
hi = mid - 1;
}
else {
lo = mid + 1;
}
}
return haystack[hi];
};
const getHighestPrimeNumber = n => {
const primes = [3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97];
return bisect(n, primes);
};
console.log(getHighestPrimeNumber(58) === 53);
console.log(getHighestPrimeNumber(53) === 53);
console.log(getHighestPrimeNumber(52) === 47);
A couple of notes:
getHighestPrimeNumber
so it isn't created and garbage collected on every function call. At this point, you might as well just call the binary search directly.return haystack[Math.min(hi,haystack.length-1)];
.Upvotes: 1
Reputation: 432
Seems like a field for a divide and conquer approach. Something like a Binary search:
const primes = [3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
function findHighestPrimeNumberRecursive(arr, ceiling) {
const midpoint = arr.length/2
if(arr[midpoint ] === ceiling){
// we found it!
return primes[arr.length-1];
} else {
if(arr[midpoint] <== ceiling) {
return findHighestPrimeNumberRecursive(arr.slice(0, midpoint), ceiling);
} else {
return findHighestPrimeNumberRecursive(arr.slice(midpoint, arr.length), ceiling);
}
}
}
function getHighestPrimeNumber(ceiling) {
return findHighestPrimeNumberRecursive(primes, ceiling);
}
Upvotes: 1