I spent the last week learning Clojure and generating jigsaw puzzles as part of my one-week programming retreat at the Recurse Center.

Why jigsaw puzzles? I was motivated by two things: first, I wanted a good-sized language-learning project. Secondly, I was heavily inspired by the amazing, beautiful, intricate jigsaw puzzles produced by Nervous Systems and wanted to experiment with similar-ish generative methods. (I’m a sucker for generative things and hadn’t played with generative algorithms too much before.) If you want a crazy cool puzzle, seriously, go buy one from Nervous.

I think they turned out well!

Because I have access to NYC Resistor’s laser cutter, the obvious thing to do was generate SVGs which I could then laser cut. If you haven’t worked with SVG before, it’s an XML-based format for describing vector graphics. It’s pretty easy to generate “by hand”.

Here is what an SVG looks like, if you open it up with a text editor:

<svg width= "100" height= "100" > <circle cx= "50" cy= "50" r= "40" stroke= "green" stroke-width= "4" fill= "yellow" /> </svg>

This produces a yellow circle, centered at (50, 50), with a radius of 40, and a four-pixel green outline. You can view an SVG file in any web browser, or edit it in an editor like Inkscape.

See? Easy-peasy.

I started by generating a “classic” jigsaw puzzle shape, and figuring out how to tile it.

But I wanted something more interesting than just a grid of similar puzzle pieces! My next step was to use a Voronoi diagram to draw more irregularly-sized polygons around “seed” points. At first this created some amusing failures:

Oops. This is what happens when you draw points at (x, x) instead of (x, y). Let’s fix those coordinates.

If we replace those straight lines with puzzle-piece edges, we get something that starts to look like a more interesting puzzle. There are still obviously flaws to be ironed out here (e.g. edge overlap).

I wanted to make more novel puzzle piece shapes, though, so I turned to the SVG path type. You can draw Bézier curves in SVG pretty easily:

<path d= "M 0 0 C 0 -100 50 -100 50 0 S 100 100 100 0" stroke= "blue" fill= "transparent" transform= "translate(0 400)" />

OK, here’s what it looks like when we replace our puzzle piece shape with some random-ish curves:

Add more curves and it gets even better!

I also experimented with variations on how to place the seed points for my puzzle generation. Here’s one that’s based on a circular point distribution.

Now I had some monstrously-irregular puzzle pieces to play with. Cool! I wanted to take it one step further by implementing whimsy pieces. In jigsaw jargon, a whimsy piece is a themed, recognizably-shaped puzzle piece. They might be butterflies or people or letters or…you name it!

I modified my puzzle-generator to clear space for a whimsy piece, first testing it with circular whimsy pieces.

Then, using a kd-tree, I identified the whimsy piece’s nearest-neighbors and connected it back to the rest of the puzzle. Here’s a cat!

And, finally, I took these files over to NYC Resistor and lasered them.

It took a group of us about ninety minutes to solve the cat puzzle. Not bad for four days’ work!

All of the code is available on Github at bonniee/svg-puzzle-gen. (It’s my first Clojure program, so I’m sure there are plenty of non-idiomatic things happening there.)

Dependencies / thank-yous:

trystan/voronoi-diagram

abscondment/clj-kdtree

Nervous Systems and their associated blog posts

Living Clojure, the textbook I used to learn Clojure

Recurse Center, for providing an inspiring and uplifting space in which to explore/learn/play

The various people who pair-programmed with me on this puzzle! You’re all awesome :)

Testimonials from playtesters: