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/4b8e1cfca06e63bea400afd2c3370b7b to your computer and use it in GitHub Desktop.

Select an option

Save sarah37/4b8e1cfca06e63bea400afd2c3370b7b to your computer and use it in GitHub Desktop.
Ulam Spiral + Fibonacci
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, where Fibonacci numbers are highlighted in addition to primes. You can read more about Ulam spirals on Wikipedia. I also made a 'regular' Ulam spiral.

  • Yellow: Prime number
  • Blue: Fibonacci number
  • Red: Prime AND Fibonacci number
  • Grey: Neither
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Ulam Spiral + Fibonacci</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; // point size
// the "radius" of the spiral
var n = d3.min([w, h]) / (r*2)
// Get Fibonacci numbers up to the maximum number in the spiral
var fib = [0, 1]
while (fib[fib.length-1] < Math.pow(2 * n, 2)) {
fib.push(fib[fib.length-1] + fib[fib.length-2])
}
// create svg
var svg = d3.select("#svgDiv")
.append("svg")
.attr("width", w)
.attr("height", h);
// create array with locations on the spiral
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) ?
(isFibonacci(index+1) ? "#f9320c" : "#f9c00c") : // prime + fib t/f
(isFibonacci(index+1) ? "#00b9f1" : '#ddd')) // not prime + fib t/f
)
.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);
}
function isFibonacci(input) {
return fib.includes(input)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment