Projects

eye of collatz

The Eye of Collatz is a simple video visualizing the Collatz conjecture. The first thirty seconds might seem a little slow and it might not be clear what’s going on, so feel free to click on the annotation that takes you to the exciting part. Technically, each pixel in the video matters to the visualization, so I recommend high quality settings on full screen:

There. Depending on how long you watched, you’ve now seen somewhere between zero and 180 000 of the hailstone sequences that Collatz conjectured about. Hopefully it was pretty to watch, because at this point you probably don’t understand what that red swirly square has to do with Collatz.

If I were a better animator then the video might’ve explained itself, but instead I’ll do that here. Before that, though, try zooming waaay in on this raw frame image, especially where the square is only partially filled in:

Note: I've tried pretty hard to make the following zooming and panning image work across browsers and devices, but it might be a bit jittery or backwards on some combinations, like on Safari with a pinch-zoom trackpad, for example. Sorry if you're affected :)

Notice that the pattern is quite intricate at the pixel level. All of that pattern is completely mathematically determined, which I find fascinating. Now on to the understanding the math and how it produces the Eye of Collatz, if you care.

The Sequences

First you should understand the actual sequences being visualized. The sequences are called hailstone sequences, and there are a ton of visualizations and descriptions of hailstone sequences out there if you want to go deeper.

A hailstone sequence starts with a number greater than two. If that first number is even, then the next number in the sequence is smaller. But if the first number is odd, then the next number is larger. Every number in the sequence follows this formula:

hn+1 = hn / 2 if hn is even

hn+1 = 3 * hn + 1 if hn is odd

For instance:

  • 2 is even, so the next number is 1 because 2 / 2 = 1.
  • 3 is odd, so the next number is 10 because 3 * 3 + 1 = 10.
  • 4 is even, so the next number is 2 because 4 / 2 = 2.
  • 213 is odd, so the next number is 640 because 3 * 213 + 1 = 640.

The next numbers have the same formula applied, and you end up with sequences! Here are the first few hailstone sequences. You might notice something about the last number in each sequence…

{ 2, 1 }
{ 3, 10, 5, 16, 8, 4, 2, 1 }
{ 4, 2, 1 }
{ 5, 16, 8, 4, 2, 1 }
{ 6, 3, 10, 5, 16, 8, 4, 2, 1 }
{ 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1 }
{ 8, 4, 2, 1 }

And so on forever and ever. In any given sequence, the numbers can go up and down lots of times (just like hailstones in a cloud, hence the name). Also, the sequences can be long or short - the hailstone sequence starting with 32 is 6 elements long, but one starting with 27 is 112 elements long.

Despite those differences, notice that the sequences overlap. They all end with

{ 2, 1 }

Three of them end with

{ 10, 5, 16, 8, 4, 2, 1 }

And if the yet-unproven Collatz conjecture is true, then all Hailstone sequences eventually terminate at 1. That is, any start number will eventually lead to 1 by following the same formula.

For the Eye of Collatz, each number from 1 to 180 000 is plotted, but not in the normal 1, 2, 3… order. Instead, each number is plotted in the order it occurs in the sequences above. From top-left to bottom-right, and with repeated numbers ignored, that looks like this:

{ 2, 1, 3, 10, 5, 16, 8, 4, 6, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 8, ... }

But how does that list of numbers end up in the video? Each pixel in the video corresponds to a number, and in each frame, more numbers (pixels) are drawn over the black background.

The Pixel Grid

I mentioned that each pixel in the video corresponds to a number. The number-to-pixel correspondence is probably the easiest thing to understand in this post - it’s just a square spiral. 1 is dead center, and the numbers spiral out from there like this:

Square spiral grid.

I think the spiral in the video may be rotated 90 degrees compared to that picture. You might notice that the spiral is exactly the same grid as from the Ulam spiral of prime numbers.

The Colors

When a number is plotted on the grid, a smaller starting number means a darker color. For example, the pixels for the numbers 3, 10, 8, 4 have a dark color because they are first plotted from the starting number 3. However, the numbers 7, 22, 11, and 34 have a brighter color because they are first plotted from the starting number 7.

Whew.

After all that, here’s another picture.

Notice the bright and dark diagonals? And all the little light and dark pockets? How about all the different shapes like crosses and tetris pieces, or how there are vertical lines on the top, but the horizontal lines on the left? And on a larger scale, notice that there is a lot of pattern and self-similarity in all sorts of ways all across the image, but no two parts seem to be perfectly identical. All very interesting, considering this is emergent from two simple formulae and a single if-else condition.

My favorite pattern is the dark “valleys” along the main diagonals of the square. I have no explanation for it, so further experimentation is necessary. Stay tuned.

Built with Processing

The Eye of Collatz’ frames were lovingly rendered with Processing. It’s pretty awful code, if I recall. (This post came years after the video was made.) After Processing did its thing, the frames were compiled into a video with some arcane set of options passed to ffmpeg. Check out the code on the GitHub page if you dare.

mandelgrok

mandelgrok is a visual exploration tool for the Mandelbrot set. But it isn’t like any other. Sure, it’ll render the Mandelbrot set and you can zoom in. But mandelgrok’s purpose is to show you the sequences that actually determine each coordinate’s membership within the Mandelbrot set:

zn+1 = zn2 + c (where z and c are complex numbers)

You form a sequence by choosing a value for c, setting z0 to zero, and computing the subsequent values of z. Some of those sequences plotted below. Each plot is for a different value of c, and the y-axis is the distance from c to zx.

Sequence 1

Sequence 2

Sequence 3

Sequence 4

Pretty, right? Mandelgrok started as an evening project to render those sequences - I had no idea what they might look like. But after seeing those beautiful things, I needed to see more. After the odd spare weekend, I have a tool that looks like this:

Mandelgrok screencap

Check it out right here or click the screencap above!

Built with Vanilla JS

mandelgrok is all vanilla JavaScript.* It’s just a couple of .js files and one .html file. I use three canvases and some CSS to make it look the way it does. Check out the code on mandelgrok’s GitHub page.

*Well, almost pure vanilla. I used JQuery.

reportify

reportify is an issue reporting tool for GitHub repositories. It uses GitHub Auth Tokens to scrape the REST API for a repository for a complete history of issues.

Built with Node

reportify sits on top of the octonode API wrapper for Node, and it uses promises for asynchronous control flow. But it’s time for a refactor - reportify started as a tiny script to rushed to fulfill the requirements of another project, so mutating global state felt justified. It’s still reasonably readable, but all functions need to be decoupled from global state and modularized before any more features are added. Get in touch if you’re interested in helping out.

polyball

polyball is a multiplayer browser game. It’s real-time and it’s physics based, and it was an intense team effort.

Built with ES5

polyball is written in JavaScript from front to back. It’s ES5 Node in the back and it’s ES5 browser in the front. It’s also a direct insubordination to the old guard of JavaScript - polyball’s JavaScript smells a lot like Java. We’re alright with that because it works.

gump

gump is a cellular automata that tastes a lot like Conway’s Game of Life. It was my first project more complex than hello world, so its code is unsightly. But it’s quite pretty and it has surprising properties. Expect a future post on that.

Built with Java

gump is written in Processing, a subset of Java that I love to use for 2D and 3D graphics programming.