Generates an Ulam Spiral of prime numbers for the range (0, 998000].
A Pen by Riley Shaw on CodePen.
button#go Generate |
Generates an Ulam Spiral of prime numbers for the range (0, 998000].
A Pen by Riley Shaw on CodePen.
;(function() { | |
function isPrime (n) { | |
if (n > 0 && n < 6 && n!== 4) return true; | |
if (!(n % 2 && n % 3 && n % 5)) return false; | |
for (var i = 7, m = Math.sqrt(n); i <= m; i += 30) { | |
if (!(n % i && n % (i + 4) && n % (i + 6) && n % (i + 10) && n % (i + 12) && n % (i + 16) && n % (i + 22) && n % (i + 24))) return false; | |
} | |
return true; | |
}; | |
function download () { | |
var img = canvas.toDataURL('image/png'); | |
var imgLink = document.createElement('a'); | |
imgLink.href = img; | |
imgLink.download = 'ulam'; | |
imgLink.click(); | |
} | |
var i; | |
var button = document.getElementById('go'); | |
var canvas = document.createElement('canvas'); | |
canvas.width = canvas.height = 999; // gives us a center @ 500, 500 | |
var ctx = canvas.getContext('2d'); | |
var c1 = 'rgb(39, 174, 96)', c2 = 'rgb(44, 62, 80)'; | |
var dirs = [ | |
{ x: 1, y: 0 }, | |
{ x: 0, y: 1 }, | |
{ x: -1, y: 0 }, | |
{ x: 0, y: -1 } | |
]; | |
button.addEventListener('click', function populate1M () { | |
var redir = 3; // next number that the spiral changes direction at | |
var run = 1; // current spiral arm length | |
var dir = 0; // 0: right, 1: up, 2: left, 3: down | |
var pos = {x: 499, y: 500}; // offset x by -1; we move right before drawing | |
// start timer & main loop | |
var t1 = window.performance.now(), i = 1; | |
button.textContent = '0%'; | |
setTimeout(function drawChunk () { // draws 1% of the canvas | |
for (var c = 9980; c--; i++) { | |
if (i === redir) { | |
dir = (dir + 1) % 4; | |
if (dir % 2 === 0) run++; // run increases when switching left or right | |
redir += run; | |
} | |
pos.x += dirs[dir].x; | |
pos.y += dirs[dir].y; | |
ctx.fillStyle = isPrime(i) ? c1 : c2; | |
ctx.fillRect(pos.x, pos.y, 1, 1); | |
} | |
if (i < 998000) { | |
button.textContent = (i-1) / 9980 + '%'; | |
setTimeout(drawChunk, 1); | |
} else loopDone(); | |
}, 1); | |
function loopDone () { | |
var t2 = window.performance.now(); | |
download(); | |
// log execution time in seconds | |
console.log('Main loop execution took ' + | |
((t2 - t1) / 1000).toFixed(2) + 's'); | |
button.textContent = 'Regenerate'; | |
} | |
}, false); | |
})(); |
$light: rgb(39, 174, 96) | |
$dark: rgb(44, 62, 80) | |
body | |
background: $dark | |
button | |
position: absolute | |
top: 50% | |
left: 50% | |
height: 2em | |
width: 8em | |
margin: -1em -4em | |
border: 0 | |
border-radius: 0 | |
outline: 0 | |
font: 24px Open Sans, sans-serif | |
background: $light | |
color: $dark | |
cursor: pointer |