Skip to content

Instantly share code, notes, and snippets.

@sarah37
Last active March 17, 2019 18:03
Show Gist options
  • Select an option

  • Save sarah37/0fcda1217e71e42afd43cf0b821b5809 to your computer and use it in GitHub Desktop.

Select an option

Save sarah37/0fcda1217e71e42afd43cf0b821b5809 to your computer and use it in GitHub Desktop.
Animated Ulam Spiral
redirect: https://observablehq.com/@sarah37/ulam-spirals

An Ulam spiral is constructed by writing the positive integers in a square spiral and highlighting prime numbers. This is an animated version of it. You can read more about Ulam spirals on Wikipedia. I also made a version of this where Fibonacci numbers are highlighted in addition to the primes. Find it here!

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Ulam Spiral</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<div id="svgDiv"></div>
<script type="text/javascript" src="sketch.js"></script>
</body>
</html>
var w = window.innerWidth;
var h = window.innerHeight;
var r = 3;
var n = d3.min([w, h]) / (r*2)
// create svg
var svg = d3.select("#svgDiv")
.append("svg")
.attr("width", w)
.attr("height", h);
var xloc = [0]
var yloc = [0]
for (var i = 1; i <= n; i++) {
// odd: down, right
// even: up, left
// odd
if (i % 2 != 0) {
// down
var x = xloc[xloc.length - 1] // get last item in xloc (current coordinate)
var y = yloc[yloc.length - 1]
for (var j = 1; j <= i; j++) {
xloc.push(x)
yloc.push(y + j)
}
// right
var x = xloc[xloc.length - 1]
var y = yloc[yloc.length - 1]
for (var j = 1; j <= i; j++) {
xloc.push(x + j)
yloc.push(y)
}
}
else {
// up
var x = xloc[xloc.length - 1]
var y = yloc[yloc.length - 1]
for (var j = 1; j <= i; j++) {
xloc.push(x)
yloc.push(y - j)
}
// left
var x = xloc[xloc.length - 1]
var y = yloc[yloc.length - 1]
for (var j = 1; j <= i; j++) {
xloc.push(x - j)
yloc.push(y)
}
}
}
var index = 0;
var timer = setInterval(addCircle)
function addCircle() {
svg.append('circle')
.attr('cx', (w/2) + r * 2 * xloc[index])
.attr('cy', (h/2) + r * 2 * yloc[index])
.attr('r', r)
.style('fill', (isPrime(index+1) ? 'red' : '#ccc')
)
.append('svg:title')
.text(index+1)
index++
if (index >= xloc.length - 1) {clearInterval(timer)}
}
// https://forum.tutorials7.com/1896/check-if-a-number-is-prime-in-javascript
function isPrime(input) {
let prime = true;
for (let i = 2; i <= Math.sqrt(input); i++) {
if (input % i == 0) {
prime = false;
break;
}
}
return prime && (input > 1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment