One of the joys and challenges in the construction of Islamic geometric patterns is choosing combinations of star shapes. In the Moroccan zellij style, for example, we often see a very large central star, with as many as 96 points, surrounded by layers of peripheral geometry. Here’s a photo I took in Fez (I think of the floor of a carpet shop), featuring an 80-pointed central star.

The challenge when designing around a large star is to reconcile its high order of symmetry with the field of more standard shapes that surrounds it. The goal is to make the complete design appear natural and seamless. That’s an exceedingly difficult design challenge, one that increases in difficulty as you try to integrate larger stars.

In this paper we take a simpler approach to constructing designs with large stars. Instead of merging the star into a field of other shapes, we grow concentric rings of motifs outward from the centre to any desired distance. If you do this naively, motifs will grow larger and larger as you move farther from the star. Most of the meat of the paper is about preventing that from happening: we gradually step down the sizes of motifs to counteract their natural scaling with distance. The result doesn’t necessarily display the incredible ingenuity of zellij patterns like the one above, but we gain the ability to create designs with stars of any size. And because of the details of the construction, larger is better!

Here’s an example from the paper, a design featuring a 184-pointed central star. Click on it to view a zoomable PDF version, where you can see the individual elements of the design in full detail.

If you’d like experiment creating your own designs in this style, we’re pleased to offer you a browser-based app that John wrote:

In the app, you grow a “core sample”, a radial slice of polygons that gets repeated around the outside of a central regular polygon. The grid of buttons in the central region of the left sidebar offers you a varying set of choices for legal rings of polygons you can glue on to the outside of the current design. The buttons at the top left let you choose whether to look at the tiling or the corresponding geometric pattern. On the right you see visualizations of the core sample above, and the finished design below. If you’d like a larger view, you can also use a separate fullscreen version of the app.

As always, full details are in the paper, which is available online at the Bridges Archive.

Amusing side note: the main email address associated with this website is isohedral@isohedral.net; that’s not my primary address, but all mail to that address gets delivered to me. For many years, John used the email address anisohedral@yahoo.com. I’m isohedral, he’s anisohedral. We should be mortal enemies, and yet we somehow found a way to bridge our differences and work together.

]]>Last year, during the excitement of Swirled Series, Robert Fathauer posted an animation on Twitter that involved squares opening and closing by rotating around hinges at their corners. Here’s my reproduction of his animation:

Tilings like these, based on alternating arrangements of squares and rhombs, are ancient. And in the twentieth century, a few people experimented with this hinged motion. I particularly like the essay by Duncan Stuart, then a student at the UNC School of Design, though the most famous use of this mechanism was probably Buckminster Fuller’s Jitterbug.

What’s interesting to me is that partway through Robert’s animation, when the hinges are open to 90 degrees, you get another tiling by squares:

There’s an intriguing opportunity here! If you rotate the whole design by 45 degrees as you open the hinges, and zoom in a bit, you can make the squares line up and produce a closed loop. This is an example of my favourite sort of looping mathematical GIF, a “strange loop” that repeats, but in a paradoxical sort of way. (Note also that the rotation of the plane exactly cancels out the rotation of the central square, which now sits fixed in the middle of the animation.)

However, this strange loop presents a new challenge. How can we colour in the squares so that the colours cycle too? Let’s assume that we want to choose colours so that adjacent squares never have the same colour (which we call a “map colouring”), but the whole design repeats after a fixed number of unfoldings. It’s not obvious how to do this. Certainly, you can’t just start with a checkerboard—Robert’s original loop demonstrates that you’ll need to reveal a third colour as soon as you unfold once. How many colours will you need? And for a given initial colouring, how many times will you have to unfold in order to get back to the colouring you started with?

My Bridges paper explores these questions. I prove that you’ll always need at least *five* colours in any looping map-coloured animation. I then demonstrate two ways to create loops that use exactly five colours.

The first solution uses a kind of pragmatic computer science approach: stumble blindly forward, always using a legal colour at each unfolding, and stop when you discover that you’ve formed a closed loop. It’s easy to see that you must close the loop eventually, and fortunately it always takes just six unfoldings in practice. You end up with lovely loops like this one, that clearly have a lot of structure but aren’t highly repetitive in space:

The second approach is more mathematical: investigate the underlying structure of these unfoldings, and try to devise a minimal loop with as much repetition as possible. Through a bit of experimentation, I came up with a cycle of two unfoldings, where each colouring is simple and elegant: copies of a colour lie in a grid, separated from like colours by knight’s moves. Here’s the animation:

If you’d like to look at all the details, you can find them in the paper, which is available online from the Bridges Archive.

]]>After a few years of not writing about the subject here, I’m happy to offer an update on Heesch numbers! If you want to save time, you can skip right to the paper I wrote, or experiment with the associated dataset.

Back in 2017, I wrote a series of four posts about Heesch numbers. If you like, you can get acquainted with the subject by having a look at the first post in the series. Briefly, a shape’s Heesch number is the number of times you can surround the shape by layers of copies of itself without copies overlapping or enclosing holes. In an ill-timed coincidence, these layers are usually known as “coronas”, a usage that predates COVID by many years.

Shapes with finite Heesch numbers live on the edge between order and chaos. Their boundaries are well-behaved enough to permit one or more coronas, but not so nice that they tile the plane out to infinity. We don’t know a lot about how to find shapes with interesting Heesch numbers, or even what Heesch numbers are possible. Until last year, I would have told you that the longstanding all-time record was Casey Mann’s shape with Heesch number 5. But I’m delighted to report that earlier this year, Bojan Bašić revealed a new shape with Heesch number 6! How high can these numbers go?

One of the main topics I explored in 2017 was Heesch numbers for families of simple shapes. I focused mostly on polyominoes (shapes made by gluing squares together), though I also wrote briefly about polyiamonds (made from equilateral triangles). Given a polyform known not to tile, at the time I computed a shape’s Heesch number using a brute-force search with backtracking. Such an algorithm is a bit like exploring a maze: every time you come to a branch, you try the first path you see. If that choice eventually allows you to reach the exit, great! But if you end up in a dead end, you back up to that branch and try the second path instead, and so on. If you do this consistently everywhere, remembering your choices at branches, you eventually find the exit or discover that no path leads to it. Translating this algorithm to surrounding shapes, every edge of the shape is a fork in the road, and you can choose any legal way to attach a new neighbouring shape to cover that edge. Any given choice might limit future options and lead to a dead end, in which case you have to choose a different neighbour placement. Eventually you either find a surround or discover that there isn’t one. To compute a shape’s Heesch number, you have to check if any surround can itself be surrounded, and so on for each successive corona.

That’s a painfully expensive process! It’s easy to get stuck in a kind of backtracking hell. There could be a funny wiggle far out along the shape’s boundary that always prevents the shape from being surrounded, but you might need to explore a vast garden of forking paths that all lead to that dead end. The pain is further compounded when exploring higher coronas: proving that a shape has Heesch number 1 involves generating all possible surrounds of it, just to establish that none of them can be surrounded by a second corona. A better algorithm would teleport from point to point around the shape’s boundary, finding features of its boundary that limit how coronas can form. It’s a bit like cordoning off some of the branches in a maze so you know never to explore them. But it’s quite difficult to know where to look for these features, and that still doesn’t help with higher coronas.

And so, my 2017 enumeration has serious problems. I could compute Heesch numbers only for small shapes, and even then computation time varied wildly, from a fraction of a second to weeks or longer. Some computations never produced an answer, forcing me to leave some polyominoes unclassified. And my code had other bugs, causing it to report the wrong Heesch number for some shapes. Yuck.

All that changed in 2019. In a thread on Facebook, Bram Cohen suggested that a SAT Solver could be used to compute Heesch numbers in a way that would likely outperform any hand-tuned algorithm. A SAT Solver is a tool that takes a Boolean formula as input (a bunch of variables, combined together with AND, OR, and NOT operations), and tells you whether there’s any way of choosing true and false values for the variables so that the whole formula comes out true. Bram’s idea was that you could translate the question “does this shape have Heesch number at least *n*?” into a Boolean formula whose variables represent all possible locations for copies of the shape, and let the SAT Solver grind through these variables, shaking out a subset that defined a configuration of legal coronas.

A SAT Solver isn’t a silver bullet: in the worst case, it can still get stuck in backtracking hell. But these tools are highly optimized, and are really, really good at jumping around the input problem, finding ways to limit the number of branches to explore. And that’s where the SAT Solver will win here. Any heuristics I could implement would be motivated by (and limited by!) a geometric interpretation of the problem. The SAT Solver doesn’t care about geometry: all it knows about is Boolean variables and how to avoid unnecessary work. I love the idea some problems can be solved more easily by being dumber, by thinking *less* about the intricacies of the problem domain. It reminds me of counterintuitive advice from math contests like the Putnam: sometimes, the best strategy for solving a problem is to solve a harder, more general problem instead. Quanta Magazine has a good article about using a SAT Solver in the context of a different mathematical problem.

Bram’s suggestion was spot-on. He offered a first version of the translation from geometry into Boolean logic, which we then refined by email. (I have since learned that Bram often swoops in, drops a brilliant idea into someone’s lap, and then rides off into the sunset.) The SAT Solver I used, CryptoMiniSat, has no trouble chewing through the computation of Heesch numbers of polyominoes. Its performance is extremely reliable too: on average it requires about 0.15 seconds per shape, and never more than about a minute for shapes with high Heesch numbers, completely avoiding the worst of backtracking hell. And a SAT-based approach generalizes easily to polyiamonds and polyhexes (made from hexagons) too! So, since 2019 I was able to correct errors in my previous enumeration, do away with all unclassified shapes, and extend the enumeration to higher polyominoes, polyiamonds, and polyhexes. As of this writing, I’ve computed Heesch numbers for all polyforms up to 19-ominoes, 17-hexes, and 24-iamonds.

If you’re interested in all of the technical details, I’ve written a paper on this search, which is available on arxiv.org. I’m also making a dataset available containing a few thousand polyforms and their Heesch numbers, as both text descriptions and drawings showing coronas. Below, I summarize a few of the main results.

Of course, I have to start with a new table showing Heesch numbers of polyominoes:

**Heesch numbers of polyominoes, no holes in the outermost corona**

n | non-tilers | H = 0 | H = 1 | H = 2 | H = 3 | Drawings |
---|---|---|---|---|---|---|

7 | 3 | 1 | 2 | 0-up | ||

8 | 20 | 6 | 14 | 0-up | ||

9 | 198 | 75 | 122 | 1 | 0-up | |

10 | 1390 | 747 | 642 | 1 | 0-up | |

11 | 9474 | 5807 | 3628 | 39 | 2-up | |

12 | 35488 | 28572 | 6906 | 10 | 2-up | |

13 | 178448 | 149687 | 28694 | 67 | 2-up | |

14 | 696371 | 635951 | 60362 | 58 | 2-up | |

15 | 2721544 | 2598257 | 123262 | 25 | 2-up | |

16 | 10683110 | 10397466 | 285578 | 66 | 2-up | |

17 | 41334494 | 40695200 | 639162 | 130 | 2 | 2-up |

18 | 155723774 | 154744331 | 979375 | 68 | 2-up | |

19 | 596182769 | 593856697 | 2325874 | 198 | 2-up |

What a difference! Whereas before I couldn’t even deal with all 700000 14-ominoes, here I’ve handled 1000 times as many shapes. The search even turned up the two smallest polyominoes with Heesch number 3, when *n* = 17. In the paper I offer a second table, giving alternate Heesch numbers when holes are permitted in the outermost corona. Click on the link in the rightmost column for a PDF from the dataset containing either all non-tilers (0-up) or shapes with Heesch number 2 and higher (2-up).

If tables of numbers make your eyes glaze over, let’s pause to look at a couple of examples. Here are some sample polyominoes with increasing Heesch numbers: a 7-omino with H = 1, a 9-omino and a 15-omino with H = 2, and two 17-ominoes with H = 3. Remember that none of these shapes tile the plane!

But wait, there’s more. Here are the Heesch numbers of hole-free polyhexes. There are a half dozen with Heesch number 4!

**Heesch numbers of polyhexes, no holes in the outermost corona**

n | non-tilers | H = 0 | H = 1 | H = 2 | H = 3 | H=4 | Drawings |
---|---|---|---|---|---|---|---|

6 | 4 | 3 | 1 | 0-up | |||

7 | 37 | 5 | 25 | 6 | 1 | 0-up | |

8 | 381 | 70 | 264 | 44 | 3 | 0-up | |

9 | 2717 | 825 | 1822 | 67 | 3 | 2-up | |

10 | 18760 | 8248 | 10234 | 265 | 13 | 2-up | |

11 | 116439 | 67644 | 47940 | 817 | 37 | 1 | 3-up |

12 | 565943 | 431882 | 133484 | 567 | 10 | 3-up | |

13 | 3033697 | 2565727 | 466159 | 1783 | 27 | 1 | 3-up |

14 | 14835067 | 13676416 | 1156793 | 1836 | 22 | 3-up | |

15 | 72633658 | 69871458 | 2758485 | 3534 | 179 | 2 | 3-up |

16 | 356923880 | 350337478 | 6581529 | 4818 | 54 | 1 | 3-up |

17 | 1746833634 | 1731652467 | 15167876 | 13129 | 161 | 1 | 3-up |

In the drawings below, the top row shows 6-hexes with Heesch numbers 1 and 2, the 7-hex with Heesch number 3, and the 11-hex with Heesch number 4.

And completing the enumerations, here’s the table for polyiamonds, including a single example with Heesch number 4:

**Heesch numbers of polyiamonds, no holes in the outermost corona**

n | non-tilers | H = 0 | H = 1 | H = 2 | H = 3 | H=4 | Drawings |
---|---|---|---|---|---|---|---|

7 | 1 | 1 | 0-up | ||||

8 | 0 | ||||||

9 | 20 | 11 | 9 | 0-up | |||

10 | 103 | 44 | 55 | 3 | 1 | 0-up | |

11 | 594 | 236 | 346 | 11 | 1 | 0-up | |

12 | 1192 | 826 | 364 | 1 | 1 | 0-up | |

13 | 6290 | 4360 | 1884 | 24 | 2 | 2-up | |

14 | 18099 | 14949 | 3141 | 8 | 2-up | ||

15 | 54808 | 48108 | 6661 | 39 | 2-up | ||

16 | 159048 | 148881 | 10153 | 13 | 1 | 2-up | |

17 | 502366 | 474738 | 27544 | 83 | 1 | 2-up | |

18 | 1374593 | 1341460 | 33100 | 33 | 2-up | ||

19 | 4076218 | 4001470 | 74689 | 57 | 2 | 2-up | |

20 | 11378831 | 11282686 | 96091 | 51 | 2 | 1 | 2-up |

21 | 32674779 | 32505745 | 168959 | 73 | 2 | 2-up | |

22 | 93006494 | 92740453 | 265977 | 62 | 2 | 2-up | |

23 | 264720498 | 264216706 | 503651 | 140 | 1 | 2-up | |

24 | 748062099 | 747476118 | 585571 | 384 | 26 | 2-up |

Below are the 7-iamond with Heesch number 1, three 10-iamonds with Heesch number 2, a 10-iamond with Heesch number 3, and the 20-iamond with Heesch number 4.

I’m glad these enumerations are out there in the world. Casey Mann’s work on Heesch numbers of polyforms with markings is excellent, but I felt sad for the poor *un*marked polyforms, which deserved to be explored.

I might try extending the enumerations above, but I’m not excited about the prospect given that the next step for any of the polyform types will burn* a lot* of CPU cycles, at least without another quantum leap in performance. I’m more interested in looking for other kinds of shapes that might lead to high Heesch numbers. I have a student working on the subject with me this summer (following yet another lead suggested by Bram), so stay tuned for new results!

In the late autumn, we reach the time of year when it’s dark outside as we sit down to dinner. During those months, we like to have candles lit while we eat. Now, it’s easy enough to blow out the candles at the end of the meal, but that’s somewhat boring too. It also has the unfortunate side effect of spraying drops of wax over the dining room table.

We’ve talked for months about acquiring a snuffer for putting out candles. Over one meal, we even talked about fun snuffer designs that would depart from the canonical “cone at the end of a stick” shape. Based on that conversation, and following a bit of 3D modelling, I came up with the following design, mimicking a marshmallow on a stick.

The snuffer is 3D printed in aluminium. That was the only material offered by Shapeways that’s both heat resistant and feasible for this particular 3D shape. The result is fun, pretty, and comfortable to hold.

And as you can see in this action photo, it works great:

I haven’t played much with 3D printing in a couple of years. My favourite experiments used to be coffee and espresso cups, fabricated using the now-discontinued porcelain process formerly offered by Shapeways. I’m sure that they, or someone else, will start up a new food-safe porcelain process in the future, if the production pipeline can be streamlined. In the meantime, I suppose I’ll be working with plastic and occasional metal.

That’s it for custom-designed 2020 holiday presents. Happy holidays!

]]>For a few years now I’ve been a fan of Redbubble as a place to pick up fun laptop stickers; I’ve created some of my own as well. Earlier this year I noticed that they had added the ability to design custom socks. I knew immediately that I would have to create my own sock designs for my family this year. Everyone opened their gifts this morning, so now’s a good time to share the results of my efforts.

My son is saving up for a fancy gaming rig. At present he can’t afford a top-of-the-line GPU, but he can have the next best thing: top-of-the-line GPU socks. The pattern on the socks is inspired by the AMD Radeon RX 6900 XT, with two exceptions. First, the Radeon has only three fans, but I added a fourth to take up the length of the sock. Second, I added coloured glows because everyone knows that your gaming rig should be filled with gratuitous lighting effects.

My daughter is a connoisseur of cats, memes, and cat memes. In her honour I created socks that depict the most important cat archetypes. They’re a bit hard to see in the photo above; here’s a field guide.

The archetypes are a mixture of doodles, traced photographs, and drawings loosely based on real cats (the smol on the right is our cat Pandora when she was about eight weeks old).

My wife is the real sock expert, a talented knitter who has made many pairs of socks for family and friends. It seemed natural, then, that she should receive socks with a pattern of socks on them. Most of the socks are in styles that one might knit (though there’s a gym sock in there too), and you’ll see that one sock is still on the needles.

These socks were created based on the tastes of my family members, and this post is certainly not intended as an ad, but if you happen to want a pair you can buy them directly from Redbubble by visiting my shop. Happy holidays!

]]>Early in November, Daniel Piker (aka @KangarooPhysics) suggested that a group of people could get together online, and each create a short segment of animation, arranged so that all the start and end frames are identical. We could then assemble all the segments into one long loop and enjoy each others’ work. The idea was based on loops that I had been posting on Twitter for fun, under the hashtag #swirlysquaresunday, and for that reason I called the group project Swirled Series.

Well, wow. I had hoped that maybe I would collect 10–20 submissions, and assemble a short video around a minute long, which could be shared on Twitter. I guess I wasn’t the only one looking for a creative outlet! In all, I received 115 loops from 81 contributors, totalling over six minutes of animation. I am honoured and humbled to serve as the curator of such a fun and diverse collection.

The best way to watch Swirled Series is at the top of this page. The animation is constantly remixing 115 short video clips, playing them in random order. You can also control the speed (I find it looks good slowed down a bit). Finally, I’ve uploaded a video to YouTube, showing the 115 loops in a fixed random order. If you’re on a small device like a phone, and the videos are cut off, you might have better luck with a separate page containing just the viewer.

Of course, none of this would be possible without the tremendous response from an enthusiastic community of creators! Thanks to @C010011012, @CyanidesDuality, @FlyingOctopus0, @GeometryDad, @SlimRunner, @TilingBot, @beesandbombs, @jn3008, @sandvrs, @teadrinker, 落葉子, Zach Abel, Dan Anderson, Dan Bach, Sebestyén Balázs, David Berardo, Daniel Berio, Elijah Bevers, Jim Bumgardner, Dina Buric, Neil Butler, Toby Cathcart Burn, Paul Chaikin, Tim Cieplowski, Tom Edgar, Matt Enlow, Frank Farris, Tony Finch, Lucas Garron, Sam Gates, Pierre Gidel, Andrew Glassner, John Golden, Chris Hanusa, Edmund Harriss, Sam Hartburn, Esther Hecky, Ian Henderson, Matthew Henderson, Jason Hise, Martin Holtham, Chris Johnson, Alex Jones, Roman Karavia, Roni Kaufman, Elliot Kienzle, William Knowles-Kellett, Eryk Kopczyński and Dorota Celińska-Kopczyńska, Tom Lechner, Jose Linares, Colin Liotta, Xing Liu, Nan Ma, Olivier Mercier, Fabrice Neyret, Andrew Osborne, Dave Pagurek, Jon Palin, Vincent Pantaloni, Juan Carlos Ponce Campuzano, David Reimann, Ricky Reusser, Juan Rinaudo, Jesus Rivera, Tanner Rogalsky, Chip Rollinson, Toby Sargeant, Henry Segerman and Saul Schleimer, Tomas Sirgedas, Ben Sparks, Zachary Stein, Tim Straubinger, stuebinm, Rashmi Sunder-Raj, David Swart, Patrick Traynor, Adrian-Teodor Tudorică, Jason Tully, Joachim Wedekind, August Wiklund, and Stasiu Wolanski. (Please tell me if I’ve left your name out or otherwise messed it up—with so many people, there could very well be mistakes!) And special thanks to Daniel Piker for gettting the whole project going.

These submissions constitute a non-trivial dataset, comprising over 18,000 frames and nearly a gigabyte of data. That’s enough information that aggregate measurements of the process become interesting. Here are a few observations.

- People were allowed to submit a loop of up to 180 frames. The average submission was 158 frames, and the majority of submissions were 180 frames—most artists wanted their full 3.6 seconds of fame!
- It would be interesting to categorize the visual and mathematical devices used to create loops. You’ll see fractals, complex numbers, non-Euclidean geometry, aperiodic tilings, physics simulation, 3D animation, strange loops, and all sorts of other sequences. In some ways the project provides an entertaining overview of techniques in mathematical art.
- The first and final frames were required to be identical 8 × 8 checkerboards of black and white squares, in a 512 × 512 PNG image. You’d think that there wouldn’t be a lot of variability in the files for those frames. Ha! Of all the files containing starting frames, the smallest was a meagre 214 bytes (way to go, Lucas Garron!) and the biggest was around 750 KB (what’s up with that, Chris Hanusa?). That’s about a 3000× difference in size, which I suppose says a lot about variation in PNG encoding algorithms.
- Information theory offers interesting measurements here too. To a first approximation, an image that’s visually simpler will be represented by a smaller file (assuming you’re using a good encoder!). Here are 115 superimposed graphs, showing a measurement of the file size of each frame in a loop over its lifetime:

Each graph shows a loop’s frame file sizes as a fraction of the average size for that loop, represented by the black horizontal line (to which all graphs have been normalized). The most obvious trends are that most animations tend to start simple and end simple (naturally, since checkerboards are simple and you’re expected to do something interesting in your loop), and that there’s a noticeable dip in the middle (many loops go through two “phases”, delineated in the middle by a relatively simple pause). I’m left wondering what other measurements I could extract, though it would make sense to re-encode the frames first with a standardized compression algorithm. - This project required a lot of manual labour. First, I maintained a spreadsheet of submissions and collected them manually via email. Then, many submissions contained errors. The most common errors were incorrectly named or numbered files. There were occasional problems with file formats or resolutions. And a lot of people submitted loops that started and ended with a black square in the lower-right corner, where I had asked for a white square. The process would definitely benefit from automated submission and validation!
- Many different tools were used to produce submissions. I’m aware of people using Processing, GeoGebra, Shadertoy, and Desmos, and that’s just for starters.

Based on the enthusiasm of the many contributors, I can certainly imagine doing this again, though perhaps not right away. I would likely restrict submissions to one per person to keep from being inundated. Ideally I would also automate the process of collecting and validating submissions.

This was a fun experience, thanks again to all the contributors!

]]>Earlier today, Daniel Piker suggested that it would be fun for a group of people interested in these looping mathematical animations to collaborate. Each would contribute a short sequence that begins and ends with a checkerboard, and we’d glue them together into one longer animation. What a lovely idea! The most famous example of this variety of collaborative artwork is what the Surrealists called an Exquisite Corpse. Exquisite Corpse *animations* are popular too; I’ve long been a fan of The Zoomquilt, and I’ve seen it done as a group project in animation courses.

So, let’s create a Swirled Series!

If you’re reading this, you’re invited to submit a short animation loop. I’ll stitch them together into a final sequence. Let me lay down some rules in order to keep the process sane:

- Use a resolution of 512×512.
- No colour, but it’s OK to use grey levels beyond pure black and pure white.
- Your segment should have at most 180 frames (I’ll aim to play back at 50 frames per second). It’s OK to have fewer frames.
- Your segment should begin and end with the same frame: an 8×8 checkerboard (i.e., squares of dimension 64×64), with white in the lower-right corner.
- You can do anything you want to get from a checkerboard back to a checkerboard, except sit still.
- I strongly recommend that your loop have “zero derivative” at the first and last frames; that is, it should glide to a graceful stop, so that the transition to the next animation in the sequence isn’t jarring.
- I would prefer to receive your submission in the form of a zip file containing a directory of PNG images named
`frame000.png`

,`frame001.png`

, …`frame179.png`

. - You grant me a non-exclusive, irrevocable license to use your images non-commercially, in animations, for education and research. Conceivably, if the result is entertaining, I might submit it to, say, the Bridges Short Film festival. In all cases, contributors will receive appropriate credit.
- The deadline is
**Friday, November 27th**. I’ll aim to publish the result the following week.

To contribute, send your zipfile to me at `swirledseries@gmail.com`

, or send me a link where I can download it.

In the unlikely event that this becomes popular, it’s possible I’ll receive more submissions than I know what to do with. In that case, please accept my apologies in advance as I work out some sort of compromise. I may have to choose who gets in by lottery or submission order, and impose a limit of one submission per person. Most likely, I’d simply keep doing this and roll extra submissions into future animations.

Thanks for playing with us!

]]>Early in the course I introduce Boolean values and conditional evaluation (we use the language Racket in this course, and teach the special form `cond`

here; other languages might use an `if`

statement). As a case study of using `cond`

, I explore speeding fines. Here’s the problem setup:

If you’re caught driving over the speed limit on Ontario highways, you might be punished with a fine. The precise amount of the fine depends on how fast you were driving. As of 2019, the penalty structure was as follows:

Amount by which you exceeded the speed limit |
Amount you pay |

Less than 20 km/h | $3.00 per km/h over the speed limit |

At least 20 km/h but less than 30 km/h | $4.50 per km/h over the speed limit |

At least 30 km/h but less than 50 km/h | $7.00 per km/h over the speed limit |

At least 50 km/h | $9.75 per km/h over the speed limit. |

(Highway Traffic Act, 1990)

Let’s turn this into a function `speeding-fine`

that consumes a speed in km/h and produces the corresponding fine.

The lesson goes on to present the solution, which looks like this:

(define (speeding-fine speed) (cond [(< speed 100) 0] [(and (>= speed 100) (< speed 120)) (* 3.00 (- speed 100))] [(and (>= speed 120) (< speed 130)) (* 4.50 (- speed 100))] [(and (>= speed 130) (< speed 150)) (* 7.00 (- speed 100))] [(>= speed 150) (* 9.75 (- speed 100))]))

If Racket isn’t your cup of tea, don’t worry about it too much. The important part of the function definition is the line `[(< speed 100) 0]`

, which translates to “if your speed was less than 100 km/h, you pay a fine of zero dollars”.

On the discussion boards, a student made this observation in response:

It’s just a technicality since the math works out either way, but the first condition should be

`[(<= speed 100) 0]`

rather than`[(< speed 100) 0]`

because there is no fine for driving exactly at the speed limit. All the subsequent iterations of the example have the same issue.

In other words, driving at precisely 100 km/h should count as “not speeding”, whereas I counted it as “speeding” (by omitting it from the first condition). The choice of `<`

vs. `<=`

doesn’t affect the result of the computation, but there’s a philosophical question here. What do you think? Did I make a mistake?

In fact, I thought about this quite a bit when writing this lesson, so I had a comically long answer for the student. I created this post to share that response. (I was particularly pleased to be able to incorporate recent current events by suddenly pivoting to an unexpected connection. It’s a rhetorical device that I definitely borrowed from the blog of my old friend Eric Lippert.)

Hi, author of the course here. I’m *delighted* that you raised this point. I went back and forth several times over the choice of `<`

vs. `<=`

in that example. I think it’s actually a very subtle question, and I could probably write a 5000-word essay about it. I won’t! But let me try to explain my choice.

**Note to students: this is beyond anything you need to care about. As the poster notes, this is a technicality, because it doesn’t affect the behaviour of the function (why not?). So feel free to ignore this and complete Module 02 without thinking about it.**

The main reason I went with `<`

is for consistency with the other conditions. The law definitely says, e.g., “less than 20 km/h” to define a tier for the fine structure, so we know we’ll need a `<`

in the second and all subsequent cases. I thought the code would look simpler with a `<`

for the speed limit too, and I had the luxury of making that choice because it doesn’t matter mathematically (whereas it *does* matter at the higher tiers).

But there’s a subtler mathematical point here. What *is* speed? In particular, is it a continuous or discrete quantity? There’s only one person qualified to answer this question: the rapper Kanye West.

Earlier this year, Yeezy announced that he was running for President of the US. It was only later that he realized that you can’t just *say* that and have it be true—there are forms to fill out, signatures to gather, etc. You have to get on the ballot in every state. He tried to get on the ballot in Wisconsin, which had a filing deadline of 5:00pm on August 4th. He submitted the forms 14 seconds after the stroke of 5:00pm, and was told that the deadline had passed. Predictably, his lawyers sent a 23-page complaint to the election commission, arguing that the entire minute of 5:00pm technically counts as On Time, because the law doesn’t talk about seconds. (See this article for more.)

So, what *is* a deadline? Is it a finite interval of time, like “the minute of 5:00pm”? Or is it an instantaneous transition from “on time” to “late”? And what’s a speed limit? Is it a continuous range of speeds, say [100,101) km/h, or is it the infinitesimal transition from less than 100 to more than 100? If it’s instantaneous, what would it mean to file your paperwork at *exactly* 5:00pm, or to travel at *exactly* 100 km/h? The, uh, good news is that it’s physically impossible to do either; or rather, the laws of physics don’t permit us to measure time or speed accurately enough to know that you’re doing that. Given enough digits of precision, every clock and radar gun will put you either before the threshold or after it, never on it.

I doubt any of this has ever been tested in court (but I would *love* to see that happen). The real world just isn’t set up to make these kinds of distinctions, and thank goodness. We avoid these transitional areas—you might get pulled over for going 10 km/h over the speed limit, but probably not for going 0.1 km/h over the speed limit (I hope you can afford the $0.30 ticket). And so, from a surprisingly deep philosophical perspective, I didn’t sweat the difference between `<`

and `<=`

too much in writing the function, because it can’t possibly matter.

By the way, watch for this point to arise again in the course, in Lesson 04.7. There, I make a metaphor with Racket sports, and the question of whether “on the line” is in or out.

Have a good weekend!

]]>I’m freshly back from a weekend in Toronto, where I was participating in the Winter meeting of the Canadian Mathematical Society. I don’t normally attend math conferences, but this time around I was invited to a session entitled “The Art of Mathematics”, and it seemed natural to join in. As it happens, the session was mostly about using art in the context of mathematics *education*; my research, which uses math to make new art, was something of an outlier. Nevertheless, I saw lots of terrific ideas for deploying art in the mathematics classroom, and snuck into a second session on increasing diversity, something both math and CS desperately need.

I spoke about “Mathematical Animated GIFs”, an art form I’ve been tracking online for at least a few years now. I focused exclusively on artworks, setting aside both animated diagrams and memes. I made my own contribution to the genre at Bridges this year, with a paper on animated tilings; I plan to summarize that work and showcase the results in a separate post. Here I’ll offer a list of the artists, artworks, and visual devices I showed in my talk, in case anybody would like to review them and discover more.

I’d love to spend lots of time discussing the many artistic merits of the people mentioned below, but I’ll take a just-the-facts approach and list them. For each artist I showed two representative works.

**David Whyte, AKA beesandbombs**(www.instagram.com/davebeesbombs/)

I showed cylinders and wavy square (my names for them).**Paolo Ceric, AKA patakk**(patakk.tumblr.com/)

I showed twisty triangle and tube (my names).**Matthew DiVito, AKA mrdiv**(mrdiv.tumblr.com/)

I showed cage and diamond_lines.**David Szakaly, AKA davidope**(dvdp.tumblr.com)

I showed 140104 and 130207.**Charlie Deck, AKA bigblueboo**(bigblueboo.tumblr.com/)

I showed cube spiral and cube chasers.**A few of mine**

I showed some of my past experiments: concentric waves, Gingham Vortex II, and a hypocycloid juggling pattern.

Here are additional pointers to artists and their GIFs, which I’m adding to this post as they are suggested to me. Check back later for more!

- Matt Enlow offered a pointer to his work in the comments below.
- Andrew Glassner created many lovely animations using Processing. A lot of these are demonstrations for his online introductory programming course.

In my talk, I offered some thoughts on the toolkit of visual devices that these artists rely on in order to create looping animations. These devices are important, because a loop that’s too simple might come across as more “obvious” or less artistic. For each device, I showed two examples.

**There and back again:**Evolve outward to some point, then reverse what you did so you return to a point where you can close the loop. I showed polygons by Rob Cramer and 190622 by davidope.**Closed parameter loop:**Construct a design that lives in a space controlled by a small number of parameters. Then move through a closed, continuous path in that space of parameters. I showed 190725 by davidope and Fabergé Fluctuation by Tom Beddard (AKA subblue).**Figure/ground duality:**Break a loop into multiple “chapters”, where in each chapter a different subset of the elements in the design plays the role of foreground and animates over top of the remaining elements. Beesandbombs is surely the master of this form; I showed discs/squares and heptominoes.**2D/3D interplay:**Some artworks explore designs based on three-dimensional geometry, but which take on a strongly 2D interpretation from a specific viewpoint. That 2D interpretation is often “brittle”, in the sense that it can be used as a junction point in the animation to move to other 3D forms. I showed negative cube by bigblueboo and spincubes by beesandbombs.**Strange loops:**I borrow Hofstadter’s terminology in describing a loop that doesn’t return to its starting point, but to a new configuration that happens to be indistinguishable from it, like the impossible staircase in Escher’s Ascending and Descending. The result is usually paradoxical and highly compelling. I showed subversion by bigblueboo and scaling squares by beesandbombs.

I talked a little bit about introductory techniques for making your own mathematical animated GIFs. The easiest software I’ve found for this task is Processing. Processing is a self-contained programming environment that streamlines the sorts of animated drawing tasks that you’ll need for abstract GIF art.

In older versions of Processing, there was a library for exporting animated GIFs. Sadly, that library doesn’t seem to be compatible with Processing 3, at least not without extra work. Therefore I suggest you export a sequence of frames from Processing as static images (say, in PNG format) and then stitch them into a GIF using ImageMagick. On my Mac, that means opening a terminal window, going into the directory where I’ve saved all the image files, and using a command like

`convert -delay 2 -loop 0 *.png output.gif`

Sorry if that’s brief; this post isn’t intended to serve as a complete tutorial. I did give a quick live demonstration during the talk, culminating in a creating a GIF that I tweeted on the spot.

I hope you’ll follow the links above and learn more about this hypnotic art form. The lists above are not meant to be exhaustive or rigorous, just the results of my random wanderings. A more systematic study of artists and devices would make for an excellent interdisciplinary art/CS project. You might start by looking through the posts on Colossal tagged with “GIF”. In the meantime, I encourage you to comment with links to other mathematical GIF artists I may have missed (I’d be especially happy to have more gender diversity).

]]>**WARNING: ****It seems as if there may be a problem with the rendering engine that will cause severe flickering on some devices. If you have a seizure disorder or are otherwise sensitive to flickering, please don’t start the game. Sorry about that.**

If you’d actually like to play it, I hope the controls are simple enough:

- Left and right arrow keys to move the current block around the well.
- Up and down arrow keys to rotate the current block.
- Space bar to drop.
- P to pause.

You might need to click in the game window in order to get it to recognize your keystrokes.

Because of the extreme perspective, I expect the game is largely unplayable (though playing Tetris without being able to read the well is an interesting experience, akin to blindfold chess). If you really wish to get through it (the perspective zoom at the end of the level, inspired by Tempest, is pretty badass), press the D key to activate a more conventional Tetris visualization in an overlay.

There’s not much more to say about this experiment. The whole thing is written in P5.js, with the vector display simulation operating as WebGL shaders. The game doesn’t add much to the Tetris (or Tempest) genre, though I haven’t seen a Tetris variant in which the well can be a cylinder, and that turns out to be somewhat interesting. I love musical mashups, so it’s satisfying to contemplate game mashups as well.

Thanks for playing!

]]>