Updated since reading the wikipedia definition of circular prime
There are a few things I would recommend you change in your findCircularPrimes
algorithm. First, you should note the algorithm is O(d*n^2)
where d
is the length of the max digit. If we use a hash instead of an array to store all the primes we can stop using .indexOf()
to check if a number is prime, making our algorithm O(d*n)
.
Another note is that javascript will represent large numbers in scientific notation. This is probably not important as your algorithm will crash the browser before it becomes an issue :)
I've re-implemented your algorithm using es5
methods reduce
to create the primeHash
and filter
to produce the circularPrime
list, but your old approach will work as well.
Edit stole @200_success @200_success much faster rotate
function to make the comparison a bit fairer and updated the jsperf :)
var LN10 = Math.log(10);
// Rotates the least-significant base-10 digit to the front
function rotate(number) {
return (number / 10 >> 0) +
(number % 10) * Math.pow(10, Math.floor(Math.log(number) / LN10));
}
//Find primes within range which are circular primes
function findCircularPrimes(range) {
var primes = findPrimes(range);
//use a hash of primes for faster lookup
var primeHash = primes.reduce(function(memo, prime) {
memo[prime] = true;
return memo;
}, {});
//use a hash of primes for faster lookup
var circularPrimes = primes.filter(function(prime) {
//check ciruclar primes
var nextDigit = prime;
while( (nextDigit = rotate(nextDigit)) !== prime) {
if(! (nextDigit in primeHash)) {
return false;
}
}
return true;
});
return circularPrimes;
}
Performance test of your implementation vs mine (original set of tests)
Chrome perf Firefox perf
Updated since reading the wikipedia definition of circular prime
There are a few things I would recommend you change in your findCircularPrimes
algorithm. First, you should note the algorithm is O(d*n^2)
where d
is the length of the max digit. If we use a hash instead of an array to store all the primes we can stop using .indexOf()
to check if a number is prime, making our algorithm O(d*n)
.
Another note is that javascript will represent large numbers in scientific notation. This is probably not important as your algorithm will crash the browser before it becomes an issue :)
I've re-implemented your algorithm using es5
methods reduce
to create the primeHash
and filter
to produce the circularPrime
list, but your old approach will work as well.
Edit stole @200_success much faster rotate
function to make the comparison a bit fairer and updated the jsperf :)
var LN10 = Math.log(10);
// Rotates the least-significant base-10 digit to the front
function rotate(number) {
return (number / 10 >> 0) +
(number % 10) * Math.pow(10, Math.floor(Math.log(number) / LN10));
}
//Find primes within range which are circular primes
function findCircularPrimes(range) {
var primes = findPrimes(range);
//use a hash of primes for faster lookup
var primeHash = primes.reduce(function(memo, prime) {
memo[prime] = true;
return memo;
}, {});
//use a hash of primes for faster lookup
var circularPrimes = primes.filter(function(prime) {
//check ciruclar primes
var nextDigit = prime;
while( (nextDigit = rotate(nextDigit)) !== prime) {
if(! (nextDigit in primeHash)) {
return false;
}
}
return true;
});
return circularPrimes;
}
Performance test of your implementation vs mine (original set of tests)
Chrome perf Firefox perf
Updated since reading the wikipedia definition of circular prime
There are a few things I would recommend you change in your findCircularPrimes
algorithm. First, you should note the algorithm is O(d*n^2)
where d
is the length of the max digit. If we use a hash instead of an array to store all the primes we can stop using .indexOf()
to check if a number is prime, making our algorithm O(d*n)
.
Another note is that javascript will represent large numbers in scientific notation. This is probably not important as your algorithm will crash the browser before it becomes an issue :)
I've re-implemented your algorithm using es5
methods reduce
to create the primeHash
and filter
to produce the circularPrime
list, but your old approach will work as well.
Edit stole @200_success much faster rotate
function to make the comparison a bit fairer and updated the jsperf :)
var LN10 = Math.log(10);
// Rotates the least-significant base-10 digit to the front
function rotate(number) {
return (number / 10 >> 0) +
(number % 10) * Math.pow(10, Math.floor(Math.log(number) / LN10));
}
//Find primes within range which are circular primes
function findCircularPrimes(range) {
var primes = findPrimes(range);
//use a hash of primes for faster lookup
var primeHash = primes.reduce(function(memo, prime) {
memo[prime] = true;
return memo;
}, {});
//use a hash of primes for faster lookup
var circularPrimes = primes.filter(function(prime) {
//check ciruclar primes
var nextDigit = prime;
while( (nextDigit = rotate(nextDigit)) !== prime) {
if(! (nextDigit in primeHash)) {
return false;
}
}
return true;
});
return circularPrimes;
}
Performance test of your implementation vs mine (original set of tests)
Chrome perf Firefox perf
Edit 2 Fixed the error in the code pointed out in the comment in op. Thestole @200_success much faster testAllPermutationsrotate
in pretty damn naive and I'm sure you can find waysfunction to optimize itmake the comparison a bit fairer and updated the jsperf :)
//test whether all prime permutations of a string str pass a given test
function testAllPermutations(str, testfn) {
var helperLN10 = functionMath.log(partstr, reststr10) {;
if(reststr === "") {//base case
Rotates the least-significant base-10 digit to the returnfront
function testfnrotate(partstrnumber);
}
{
forreturn (var i = 0, l = reststr.length;number i/ <10 l;>> i++0) {+
if( !helper(number partstr% +10) reststr[i],* reststrMath.slicepow(010, i) + reststrMath.slicefloor(i + 1, l) )Math.log(number) {//recurse on another variation of the string
return false;
}
}
return true;
}
return helper("", String(strLN10));
}
//Find primes within range which are circular primes
function findCircularPrimes(range) {
var primes = findPrimes(range);
//use a hash of primes for faster lookup
var primeHash = primes.reduce(function(memo, prime) {
memo[prime] = true;
return memo;
}, {});
//use a hash of primes for faster lookup
var circularPrimes = primes.filter(function(prime) {
//check ciruclar primes
var circularPrimesnextDigit = primes.filterprime;
while(function(nextDigit = rotate(nextDigit)) !== prime) {
//checkif(! ciruclar(nextDigit primesin primeHash)) {
return testAllPermutations(prime, function(permutation) { return permutationfalse;
in primeHash; });
});
return true;
});
return circularPrimes;
}
Edit 2 Fixed the error in the code pointed out in the comment in op. The testAllPermutations
in pretty damn naive and I'm sure you can find ways to optimize it
//test whether all prime permutations of a string str pass a given test
function testAllPermutations(str, testfn) {
var helper = function(partstr, reststr) {
if(reststr === "") {//base case
return testfn(partstr);
}
for (var i = 0, l = reststr.length; i < l; i++) {
if( !helper( partstr + reststr[i], reststr.slice(0, i) + reststr.slice(i + 1, l) )) {//recurse on another variation of the string
return false;
}
}
return true;
}
return helper("", String(str));
}
//Find primes within range which are circular primes
function findCircularPrimes(range) {
var primes = findPrimes(range);
//use a hash of primes for faster lookup
var primeHash = primes.reduce(function(memo, prime) {
memo[prime] = true;
return memo;
}, {});
//use a hash of primes for faster lookup
var circularPrimes = primes.filter(function(prime) {
//check ciruclar primes
var circularPrimes = primes.filter(function(prime) {
//check ciruclar primes
return testAllPermutations(prime, function(permutation) { return permutation in primeHash; });
});
});
return circularPrimes;
}
Edit stole @200_success much faster rotate
function to make the comparison a bit fairer and updated the jsperf :)
var LN10 = Math.log(10);
// Rotates the least-significant base-10 digit to the front
function rotate(number) {
return (number / 10 >> 0) +
(number % 10) * Math.pow(10, Math.floor(Math.log(number) / LN10));
}
//Find primes within range which are circular primes
function findCircularPrimes(range) {
var primes = findPrimes(range);
//use a hash of primes for faster lookup
var primeHash = primes.reduce(function(memo, prime) {
memo[prime] = true;
return memo;
}, {});
//use a hash of primes for faster lookup
var circularPrimes = primes.filter(function(prime) {
//check ciruclar primes
var nextDigit = prime;
while((nextDigit = rotate(nextDigit)) !== prime) {
if(! (nextDigit in primeHash)) {
return false;
}
}
return true;
});
return circularPrimes;
}
Edit 2 Fixed the error in the code pointed out in the comment in op. The testAllPermutations
in pretty damn naive and I'm sure you can find ways to optimize it. See http://jsbin.com/iMUWIQU/5
Edit 2 Fixed the error in the code pointed out in the comment in op. The testAllPermutations
in pretty damn naive and I'm sure you can find ways to optimize it. See http://jsbin.com/iMUWIQU/5
Edit 2 Fixed the error in the code pointed out in the comment in op. The testAllPermutations
in pretty damn naive and I'm sure you can find ways to optimize it