« | » Main « | »

Computing primes with CSS

Thursday 29 September 2016

I've been working on a redesign of this site, so doing more CSS, finally internalizing Sass, etc. During my reading, the nth-child pseudo-class caught my eye. It's oddly specific, providing syntax like "p:nth-child(4n+3)" to select every fourth paragraph, starting with the third. It isn't an arbitrary expression, it has to be of the form An+B, where A and B are integers, possibly negative. An element is selected if it is the An+B'th child of its parent, for some value of n ≥ 0.

It struck me that this is just enough computational power to compute primes with a Sieve of Eratosthenes, so I whipped up an demonstration (see it live here):

<html>
<head>
<style>
/* A stupid pet trick by Ned Batchelder @nedbat */
html { max-width: 40rem; }
span { display: inline-block; width: 2em; text-align: right; }
span:nth-child(2n+4),
span:nth-child(3n+6),
span:nth-child(4n+8),
span:nth-child(5n+10),
span:nth-child(6n+12),
span:nth-child(7n+14),
...
span:nth-child(30n+60),
span:nth-child(31n+62),
span:nth-child(32n+64),
span:first-child { display: none; }
</style>
</head>
<body>
<p>Primes:</p>
<div>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
...
<span>996</span>
<span>997</span>
<span>998</span>
<span>999</span>
</div>
</body>
</html>

The code has only linear sequences of numbers. There are spans for 1 through 999, the candidate numbers. These are arranged so that the number N is the Nth child of their containing div. The CSS has nth-child styles for 2 through 32, the possible factors.

The Sieve will hide numbers that are determined not to be primes with a "display: none" rule. A first-child selector hides 1, which is typical, seems like you always have to treat 1 specially when looking for primes. The other selectors for the display:none rule select the multiples of each number in turn. "nth-child(2n+4)" will hide elements 4, 6, 8, and so on. "nth-child(3n+6)" will hide 6, 9, 12, and so on.

So CSS has two features that together are just enough to implement the Sieve. The nth-child selector accomplishes the marking of factors. The overlapped application of separate rules implements the multiple passes, one for each factor.

Of course, I didn't write this file by hand, I wrote a Python program to do it. It's pretty simple, I won't clog up this post with the whole thing. But, it was my first use of a new feature in Python 3.6: f-strings. The loop that writes the nth-child selectors looks like this:

for i in range(2, 33):
    print(f"span:nth-child({i}n+{2*i}),")

The f"" string has curly-bracketed expressions in it which are evaluated in the current scope. This string in Python 3.6:

f"span:nth-child({i}n+{2*i})"

is equivalent to this in previous Pythons:

"span:nth-child({i}n+{i2})".format(i=i, i2=2*i)

It felt really natural to use this new feature, and really convenient.

Don't follow me on Instagram

Monday 5 September 2016

This summer I started taking pictures and posting them on Instagram. It started with a conversation with my son Max, and his assertion that posting more than one picture a day on Instagram was Instaspam. That constraint appealed to me. I like the idea of photography as a way of attending to what I am seeing. So I started trying to look around me to find interesting shots for Instagram posts.

My summer has been different than I expected, so I've had chances to look around places I didn't expect to be. Ironically, thinking about what can go on Instagram can be a way to focus on the here-and-now. You have to see what is immediately around you in order to get a shot.

Normally, thinking about stuff to post on a social network can be the furthest thing from being in the moment. You're thinking about how people will react to your tweet, or who will look at your Facebook status. It's easy to fall into second-guessing what will get the biggest response. You spend time going back to look at what happened to your recent activity.

I have mixed stances toward different social media. I like Twitter, and like having followers. I want my tweets to get widely retweeted. I ignore Facebook, except to find out what my sons are up to. Pinterest and Snapchat might as well not exist. Now I'm putting pictures on Instagram, but not to get followers or tons of likes. The photos have no message, I rarely put any words on them. If I can post a picture I like, and have one other person like it, that's enough.

If you want to follow someone good on Instagram, my brother is an actual photographer who knows what he is doing. Follow him!

« | » Main « | »