I am trying to teach myself node.js (no javascript or real programming experience) and have hit a road block on one of the problems I am trying to solve. My goal is to write the
You're doing a lot in one function. The code may be a bit easier to follow if you break it up into two functions, one to make the list of primes and another to test if a specific number is prime:
function listPrimes( nPrimes ) {
var primes = [];
for( var n = 2; nPrimes > 0; n++ ) {
if( isPrime(n) ) {
primes.push( n );
--nPrimes;
}
}
return primes;
}
function isPrime( n ) {
var max = Math.sqrt(n);
for( var i = 2; i <= max; i++ ) {
if( n % i === 0 )
return false;
}
return true;
}
Now you can run it in Node:
var fs = require('fs');
fs.writeFileSync( 'test.txt', listPrimes(100) );
or directly in the browser console:
listPrimes( 100 );
(I didn't test the code in Node, only in the browser.)
A couple of related notes:
sqrt()
calculation is moved outside the loop in isPrime()
, so it doesn't have to be recalculated for each number you're testing.nPrimes
variable lets you generate the exact number of primes you want without the 542
hack.Having written this simple version, it's interesting to look at possible optimizations. One is to check for divisibility only on the previously generated primes, instead of checking all integers up to the square root. You could do that like this:
function listPrimes( nPrimes ) {
var primes = [];
for( var n = 2; nPrimes > 0; n++ ) {
if( isPrime( n, primes ) ) {
primes.push( n );
--nPrimes;
}
}
return primes;
}
function isPrime( n, primes ) {
var max = Math.sqrt(n);
for( var i = 0; i < primes.length && primes[i] <= max; i++ ) {
if( n % primes[i] === 0 )
return false;
}
return true;
}
That may be faster if you're generating a large number of primes, although for 100 of them it hardly matters and I'd be inclined to stick with the simpler code.
Of course if you're talking about optimization, it's always worth considering a different algorithm. The Sieve of Eratosthenes is a fun one because it's fast and fairly simple and easy to understand. That Wikipedia article has a great illustration of how it works. In JavaScript it might look something like this:
function listPrimes( max ) {
// Start with an empty list of primes
var primes = [];
// Initialize the sieve - each number is prime unless proven otherwise
var sieve = new Array( max );
for( var i = 1; i <= max; i++ ) {
sieve[i] = true;
}
// Now check each number from 2 through max
for( var p = 2; p <= max; p++ ) {
if( sieve[p] ) {
// p is prime, save it in the output list
primes.push( p );
// Mark p * 2, p * 3, p * 4, etc. as non-prime
for( var t = p * 2; t <= max; t += p ) {
sieve[t] = false;
}
}
}
return primes;
}
Yes, after recommending splitting the code into two functions, I'm now back to one function. :-)
One difference about the Sieve is that you can't really say, "please give me the first N primes"; instead you ask it, "please give me all the primes less than N". But if N is a large number, it is much faster than the other approach.
This works even beter if you preinitialize the list and skip testing the primality of multiples of 2
var primes = [2];
--nPrimes
for( var n = 3; nPrimes > 0; n += 2 )
I just finished very similar code for the Startup Engineering course homework @Coursera ;)