Skip to content

Instantly share code, notes, and snippets.

@jdfm
Created September 5, 2016 01:30
Show Gist options
  • Save jdfm/874a3c0d9527be485c809b1df536545b to your computer and use it in GitHub Desktop.
Save jdfm/874a3c0d9527be485c809b1df536545b to your computer and use it in GitHub Desktop.
ES6 Exploration: Use iterator pattern to generate a prime list
const primeList = new Array(1000)
primeList[Symbol.iterator] = function(){
const buffer = [2, 3]
let bufferLength = 2
const _this = this
const thisLength = this.length
let lastChecked = 4
let count = 2
let lastPopulatedIndex = -1
const extendBuffer = ( start, end ) => {
const startModulo = start % 6
const endModulo = end % 6
const realStart = (
startModulo === 1 || startModulo === 5 ?
start :
start + (
startModulo === 0 ?
1 :
5 - startModulo
)
)
const realEnd = (
endModulo === 1 || endModulo === 5 ?
end :
end - (
endModulo === 0 ?
1 :
endModulo - 1
)
)
for(
let currentValue = realStart,
j = ( startModulo <= 1 ? 1 : 0 );
currentValue <= realEnd;
// move in increments of 2 or 4 (6n+1->6n+5->6n+1->...) depending on the current value of j
currentValue += 2 * ( j + 1 ),
j = ( j === 0 ? 1 : 0 )
){
bufferLength = buffer.push( currentValue )
}
}
const zeroOutCompositesInBuffer = () => {
// go through the buffer
for( let i = 0; i < bufferLength; i++ ){
// check the divisibility of each number in the buffer against the primes we have in our main list
for(
// we don't care about 2 or 3 as the numbers in buffer will never be divisible by either
let j = 2,
// the current prime
k = _this[ j ],
// the maximum possible number we should check buffer[ i ]'s divisibility against
maxFactor = Math.floor( Math.sqrt( buffer[ i ] ) );
k <= maxFactor;
k = _this[ ++j ]
){
if( buffer[ i ] % k !== 0 ){ continue }
// if the number was divisible by any other number, zero it out
buffer[ i ] = 0
break
}
}
}
const populateBuffer = () => {
// using a conjecture that states that there are primes between each each square number
extendBuffer( lastChecked + 1, lastChecked + 2 * count + 1 )
// update some counters used for generating the next buffer
lastChecked += 2 * count + 1
count++
// composites in our buffer will be zeroed out
zeroOutCompositesInBuffer()
}
const fetchFromBuffer = () => {
let current = 0
while(
// keep going until we've exhausted the buffer
bufferLength > 0 &&
// get the next number in the buffer, if it's not zero, the loop will stop
( current = buffer.shift() ) === 0
) {
bufferLength--
}
// if we've exhausted the buffer and our current value is zero, we need to generate another round of prime numbers
if(current === 0){
return populateAndFetchFromBuffer()
}
// at this point we've got a prime number
// update some of the counters
bufferLength--
lastPopulatedIndex++
// update our collection and return the current selected value
return _this[lastPopulatedIndex] = current
}
const populateAndFetchFromBuffer = () => {
populateBuffer()
return fetchFromBuffer()
}
return {
next: () => (
lastPopulatedIndex !== thisLength - 1 ?
{
value: (
bufferLength === 0 ?
// if our buffer is empty, we'll want to populate it and fetch the first nonzero value from it
populateAndFetchFromBuffer() :
// otherwise, just fetch the first nonzero number from it
fetchFromBuffer()
),
done: false
} :
{ done: true }
)
}
}
for(let value of primeList){
console.log(value);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment