2018

Tuesday 2 January 2018

When I was in high school, I was not a diligent student of English. I would try to do the reading on the subway ride, and not very well. One morning, I was on page 38 when I got to my stop. I didn’t have a bookmark, and I didn’t like to turn down the corners of pages, so to remember my place, I thought about what was interesting about the number 38.

Hmm, 38 is twice a prime. It’s one more than 37, which is a prime. Oh, and 39 is three times a prime. Interesting: a sequence of three consecutive numbers that are respectively 1-times, 2-times, and 3-times a prime. BTW, it worked: to this day, I remember what page I was on!

Then a recent tweet brought back this interesting confluence: 2018 has the same property. 2017 is a prime, 2018 is twice a prime, and 2019 is three times a prime.

It turns out this property is rare. There are only eleven numbers less than 3000 like this: 14, 38, 158, 542, 878, 1202, 1382, 1622, 2018, 2558, 2858; and only 541 such numbers less than 1,000,000.

So 2018 is a truly unusual year. 2017 was difficult politically, but there are hopeful signs of a turning tide. Here’s to the year ahead, and fighting the good fights: personally, locally, and nationally.

Iter-tools for puzzles: oddity

Friday 8 December 2017

It’s December, which means Advent of Code is running again. It provides a new two-part puzzle every day until Christmas. They are a lot of fun, and usually are algorithmic in nature.

One of the things I like about the puzzles is they often lend themselves to writing unusual but general-purpose helpers. As I have said before, abstraction of iteration is a powerful and under-used feature of Python, so I enjoy exploring it when the opportunity arises.

For yesterday’s puzzle I needed to find the one unusual value in an otherwise uniform list. This is the kind of thing that might be in itertools if itertools had about ten times more functions than it does now. Here was my definition of the needed function:

def oddity(iterable, key=None):
    """
    Find the element that is different.

    The iterable has at most one element different than the others. If a
    `key` function is provided, it is a function used to extract a comparison
    key from each element, otherwise the elements themselves are compared.

    Two values are returned: the common comparison key, and the different
    element.

    If all of the elements are equal, then the returned different element is
    None.  If there is more than one different element, an error is raised.

    """

The challenge I set for myself was to implement this function in as general and useful a way as possible. The iterable might not be a list, it could be a generator, or some other iterable. There are edge cases to consider, like if there are more than two different values.

If you want to take a look, My code is on GitHub (with tests, natch.) Fair warning: that repo has my solutions to all of the Advent of Code problems so far this year.

One problem with my implementation: it stores all the values from the iterable. For the actual Advent of Code puzzle, that was fine, it only had to deal with less than 10 values. But how would you change the code so that it didn’t store them all?

My code also assumes that the comparison values are hashable. What if you didn’t want to require that?

Suppose the iterable could be infinite? This changes the definition somewhat. You can’t detect the case of all the values being the same, since there’s no such thing as “all” the values. And you can’t detect having more than two distinct values, since you’d have to read values forever on the possibility that it might happen. How would you change the code to handle infinite iterables?

These are the kind of considerations you have to take into account to write truly general-purpose itertools functions. It’s an interesting programming exercise to work through each version would differ.

BTW: it might be that there is a way to implement my oddity function with a clever combination of things already in itertools. If so, let me know!

Bite-sized command line tools: pylintdb

Sunday 3 December 2017

One of the things I love about Python is the abundance of handy libraries to cobble together small but useful tools. At work we had a large pylint report, and I wanted to understand it better. In particular, I wanted to trace back to which commit had introduced the violations. I wrote pylintdb.py to do the work.

Since we had a lot of violations (>5000!) I figured it would take some time to use git blame to find the commit for each line. I wanted a way to persist the progress through the lines. SQLite seemed like a good choice. It also would give me ad-hoc queryability, though to be honest, I didn’t even consider that at the time.

SQLite is part of the Python standard library, but there’s a third-party library that makes it super-convenient to use. Dataset lets you use a database without creating a schema or even model first. You just open a database, choose a table name, and then start writing dictionaries to it. It handles all the schema creation (or modification!) behind the scenes. Awesome.

These days, click is the tool of choice for command-line parsing, and other chores needed in the terminal. I used the progress bar functions. They aren’t perfect, but in only a few lines I had a workable indicator.

Other useful things from the Python standard library:

  • concurrent.futures for parallelizing the git blame work. It’s got a high-level “map” interface that did exactly what I needed without having to think about queues, threads, and so on.
  • subprocess.check_output does the subprocess thing people usually want: just run the command and give me the output.

pylintdb isn’t earth-shattering, it just does exactly what I needed in 120 lines with a minimum of fuss, thanks to dataset, click, and Python.

New design

Saturday 25 November 2017

I’ve just updated the design of this site. The goal was to make it responsive, so that it would work well on small screens, but I made other changes along the way. The body type is now serif rather than sans, and much larger. I made lots of other tweaks as I worked on pages.

Making a responsive design was fun: it meant working out mechanisms for the layout rather than just a static design.

Of course, it’s easy to get carried away. Take a look at what happens to my name in the header when the screen gets below 300 pixels: Ned Batchelder becomes nedbat to save space. This was accomplished with the help of a span with class “chelder”...

It took me a long time to make this design. I started it 15 months ago, but stopped work on it for more than a year. I picked it up again two weeks ago, and powered through the remaining work.

Behind the scenes, I changed only one thing: using Sass to generate the CSS. The rest is still as janky and difficult as always.

For comparison (and posterity), here is the design I just replaced. If anything seems amiss with the new design, just let me know.

Candy in my pocket

Saturday 18 November 2017

Let me tell you a modern-day horror story: for almost ten days, I didn’t have a phone!

I was on a day trip to Montréal, and my phone just completely died. I thought maybe it just needed a charge, but nope, nothing would bring it back. I had a nicely sculpted chunk of glass.

(Side note: I had been texting with Susan, so eventually I dashed off a quick email: “My phone is completely dead. I can’t even tell what time it is.” She sent back an email that said just, “It’s 11:24.” Is it any wonder I love her?)

At first, I felt a bit lost. I couldn’t take pictures, I couldn’t use maps, I couldn’t text with Susan to coordinate getting picked up at the airport.

But what I noticed is that much of what I was used to doing with my phone, I didn’t really miss. I didn’t have games to jump to when I had a free moment. I wasn’t able to reflexively look up interesting tidbits. I couldn’t anxiously check if I had gotten an interesting email.

I realized I didn’t need those things. It was OK to not have a smaller screen to use when I wasn’t using my larger screen. I started to feel like the phone was like a bag of candy in my pocket. If my pocket is full of candy, I’ll nibble on candy all day long. But when I didn’t have a bag of candy, I didn’t miss it. Sure, sometimes I’d like to have a piece of candy, but not nearly as much as I ate when I always had a bag of candy with me.

Now I finally (USPS can be disappointing...) have a new phone, a Google Pixel. I’ll be glad to have my podcasts back. I can take pictures again. I was lucky not to need a two-factor app in the last week.

I’ll have to see how I relate to it. I’ll have the candy with me, but will I be able to resist nibbling? I wasn’t as bad as some: I never had the impulse to read my phone while standing at a urinal, for example. But I nibbled a lot more than it turns out I needed to. I’ll try to keep in mind how these last ten days felt, and snack responsibly.

Finding your first OSS project

Saturday 11 November 2017

Running in the circles I do, I often hear the question, “Where’s a good open source project to start off contributing to?” The last time this came up, I asked on Twitter and got some good replies.

The best answers pointed to two aggregators of projects. These sites collect links to projects that have special labels for bug reports that are good for first-time contributors to work on. The presence of these labels is a good indicator that the project is well-maintained, welcoming to newcomers, and prepared for their contributions.

  • Up For Grabs lists dozens of projects, helpfully showing how many open first-timer issues each has.
  • Awesome for Beginners is lower-tech, but also lists projects with links to their first-timer tagged issues.

I also got links to some useful advice for first-time contributors:

Making a first contribution can be overwhelming. Keep looking through these resources until you find something that makes it feel do-able.

Older: