I participated in Advent of Code for the second time this year. My notes on last year’s challenge were one of the first things I posted here, so let’s call this post a tentative continuation of that nascent series.
The most substantial change introduced in this year’s challenge was its shortening. The global leaderboards were also removed, but that wasn’t as meaningful to me, since I don’t care about leaderboards. The organizer, Eric Wastl, posted comments explaining this decision, and while some participants seemed quite put out, I fully support the decision to continue an ongoing project in a more sustainable form. Judging by some of the public negativity, I think Eric would have been more than justified in shutting the project down altogether—running a fun public project for free doesn’t obligate him to keep it going in any form—so I appreciate him taking steps to keep things going.
I have written more code in the past year than any period since I stopped working professionally as a software engineer. In contrast, last year’s challenge represented a return to programming for me, and it’s remarkable how different it felt. Last year, solving even the simplest problems brought me satisfaction, much of which came from focusing on doing things in the most Pythonic1 way.
This time around, I still found satisfaction in figuring out how to crack the problems. I think this is because programming challenges present a much higher ratio of problem to boilerplate than real world programming does. Honestly, nobody would do programming challenges if they were more realistic in that way. I can’t imagine anyone wants to spend any more time than necessary negotiating data format conversions, handling obscure protocol issues, or any of the other gruntwork that comes with real world software engineering.
What felt most different was being more familiar with Python convention. This meant that while I spent less time working out the best way to express my logic in the language, I also didn’t get as much enjoyment out of reaching those conclusions. For working programmers, that’s no loss. You literally don’t want to spend a lot of time reasoning through the right way to express yourself unless you’re writing something novel and distinctive. The point of idiom and convention is to allow a community to make correct assumptions about what a particular chunk of code does. But for hobbyists and dabblers, in whose company I count myself, it’s certainly less fun.
Thoughts on LLM Coding Assistants
I wrote all of my code myself, but because I use a modern editor, I received inline suggestions from an LLM coding assistant. If you’re unfamiliar, think of it as a kind of autocomplete for programming. Editors have offered support tools like these for decades to help programmers fill in variable names or get function signatures correct, and bringing LLMs to bear on this problem makes a lot of sense, given how unreasonably effective LLMs have proven at digesting and generating code.
Earlier this year when I was working on a different project, I found these suggestions annoying and unhelpful. In part, this was because I was doing some fairly technical processing that the assistant was clearly familiar with, but whose logic it could not accurately generate. That experience actually lowered my estimation of the usefulness of coding assistants in general, but in retrospect, I was probably coming at the problem in the wrong way.
Unlike coding agents like Claude Code, whose purpose is to build working software according to a user’s specification, inline coding assistants really do need to be approached like autocomplete. They provide a potential end for something the author has begun, and much of the time, they are incorrect, because it’s often hard to know for certain what should come next. However, when the next thing really is an obvious extension of what came before, it’s quite useful to have the editor handle the rote typing after the thinking is done.
An Example
The problem for Day 4 this year involved looking at items laid out on a grid and checking for adjacent items. My solution for Part 1 processes the input and stores the locations of the items as coordinate pairs like (1,2) to represent an item in column 1 and row 2. To look for adjacencies, my code checks all of the coordinate pairs that are one away from at least one of the coordinates, so in this case, (0,2), (2,2), (0,1), (1,1), and so on. I decided to do this by storing a list of offsets that could be added to each coordinate pair. Once I started the expression adjacency_offsets = [, the correct inline suggestion appeared:
That’s a pretty helpful suggestion, and a substantial improvement over earlier systems that could complete token names but not much else. These autocompletions don’t directly save a ton of time, but they can help programmers stay focused on problem solving by obviating some of the toil that accompanies it.
One Minor Issue
As I mentioned, I fully support shortening Advent of Code, especially if doing so makes it more likely to remain an ongoing annual event. However, I would like to suggest one adjustment to the new format for future years.
In previous years, it seems to have been typical for the final day’s challenge to be simpler than the rest. I think of it as a kind of Christmas gift to participants, and respectful of the likelihood that even dedicated participants would prefer to spend Christmas Day doing holiday things other than coding.
This year, the final challenge was released on December 12, but it seems the organizers still decided to treat it as a “gift” day, providing a challenge that seemed tricky but was actually trivially solvable without any coding. In my case, I examined the puzzle input with a spreadsheet that ended up generating the answer for me. I saw quite a few disappointed comments from participants online, and I tend to agree that Day 12 didn’t feel great. With the last day of the event no longer falling on Christmas, I think it makes sense to retire the gift day tradition and make all 12 challenges more or less equally real.
My Most/Least Favorite Problem
For me, the most notable problem this year bears striking similarities to something I wrote a bit about last year. For the second year in a row, one of the challenges boiled down to a linear algebra problem that nearly cost me a star. Much as I tried, I struggled to write a solution that could calculate answers for Part 2 of Day 10 efficiently enough.
I ended up breaking my own rule about sticking to standard libraries and brought in SciPy to handle the linear programming, rather than stumble my way through implementing Gaussian elimination by hand. On one hand, I wish I had been able to meet the challenge myself, but it’s not so bad to have a chance to refresh my memory and dip back into an extremely useful Python library. At least this year, I recognized the structure of the program at the outset instead of banging my head against it futilely for far too long.
I’ll conclude by encouraging anyone who’s interested to review my best effort using only standard libraries. Let me know if I’m missing any ways to further reduce the search space. I’m reasonably confident that the code I’ve written is correct, but it’s just not efficient enough to come up with solutions for larger cases in a reasonable time on my laptop.
In fact, just for kicks, I posted all of my solutions, which you’re welcome to check out. Until next year!
For non-coders, the different capabilities afforded by different programming languages tend to coalesce into a shared style that the community views as being most consistent with the language’s strengths and weaknesses. The community for Python, the language I used, calls this style “Pythonic.” ↩
The Best Video on Board Game Boxes You’ll See This Year
The main link I wanted to share this week is Amabel Holland’s latest video contemplation of board game boxes. As someone who doesn’t mind—even kinda likes—the beige-cardboard-everywhere feel of 90s-2000s eurogames, I’ve watched with fascination over the past few years as the hobby game world has become much more aware of the power of image and marketing. It takes someone like Amabel who takes art games and the game business seriously to really delve productively into areas like boxes and physical presentation, where the reality of games as commercial entities collides with their various other natures—artistic, ludic, or otherwise.
The Best Apocalyptic Synthwave Hammer Time Video You’ll See This Year
The Best Flickr Galler of Public Domain Images That Go Hard You’ll See This Year
This is the latest in an unintentional series I’m apparently doing in which I write about topics related to the contemporary debate over the use, usefulness, impact, and harms of generative Artificial Intelligence (genAI) inspired by weeks-old podcasts. The fact that I write these things about old podcast episodes is entirely a function of the fact that my listening backlog is regularly weeks or months long.
This time, I’m writing about an interesting passage from an episode of This American Life entitled My Other Self. The bit I’m discussing starts around 27:45 and runs for about two minutes. You can listen to it directly on the episode page or any number of locations—indeed, wherever you listen to podcasts, as the saying goes.
The part I’m interested in happens during a segment by reporter Evan Ratliff, in which he is experimenting with hooking up ChatGPT to ElevenLabs’ voice synthesizer and a telephone number. He uses this stack to call friends, waste scammers’ and telemarketers’ time, and entertain his father. In the relevant portion of the story, he invites strangers to call the number to participate in a research interview discussing their experiences with AI. Of course, none of the callers know ahead of time that they are speaking to a bot.
A remarkable exchange occurs with a survey respondent named Stephanie. Answering a question from the bot, she says she has probably interacted with AI without even knowing it. Then, half-joking, she exclaims, “Jesus! I’m probably talking to an AI right now!” The bot asks her why she said that, and she explains that the bot is speaking a bit awkwardly. The interaction is brief, and they quickly move on.
The truly remarkable moment happens just afterward. Stephanie calls back after the end of the initial call, and without exactly apologizing, expresses clear regret for hurting the interviewer’s feelings by calling them a bot.
To me, this illustrates an underappreciated effect of the proliferation of genAI agents, particularly those that are foisted on the public without notice or consent. Clearly, Stephanie was uncertain whether or not she was speaking with a bot. After she got off the phone, she did some kind of moral reckoning: what would it mean if she were in fact talking to a bot? What if she weren’t? What obligation did she feel she had to a possibly human interviewer whom she’d just suggested might be a computer? Conversely, what were her obligations to a computer that she had been led to interact with under false pretenses?
However she happened to arrive at her decision, she concluded it would be worth it to call back and try to smooth things over. And she did that knowing there was a chance she was offering a token of respect to a bot that would not only be unable to appreciate it, but in fact didn’t deserve it.
I think that the more the public is forced or tricked into using genAI, the less common Stephanie’s reaction will be. I’m not talking specifically about apologizing to ChatGPT; I’m talking about considering the feelings of an interlocutor whose humanity can’t be conclusively established.
Any time you interact with an entity that could be either human or AI, you have to decide whether to treat that entity like a person or a computer. As long as your powers of discrimination are imperfect, you run the risk of treating a person like a computer or treating a computer like a person. However, in my view, these two errors are not morally equivalent. Treating a computer like a person might be a little embarrassing, but treating a person like a computer is potentially harmful. The harms are not necessarily large: failing to apologize to someone you’ve mistakenly accused of deceiving you won’t likely do much more than hurt their feelings. But the inverse case, in which you apologize to a computer who actually was deceiving you, costs only the effort that goes into the apology.
I think a world where people don’t treat each other like people because they might be bots is unlikely to be a good world, much less a happy one.
I’ve got a lot going on for this holiday week, even before I caught whatever bug laid me low for the past 24 hours, so for links I offer a few entertaining videos: two older songs and one wild compilation.
First, a music video for a song that I remember as one of the first that really attracted me to the then-emerging “alternative” scene. Of course, at the time the only way for me to glimpse this scene was through the tiny keyholes of college radio and pre-Matt-Pinfield 120 Minutes. It’s one of those songs that takes me back to a specific point from the past, and I think the video really captures the aesthetic of a moment:
This other video, from a few years later, is for a song that I have known and loved for a long time. Strangely, though, I hadn’t seen the video until recently.
And finally, there’s this wonderful little clip compilation. As you watch it, I want to remind you that this was posted by the official Jeopardy! YouTube channel:
I was out for a run not far from the house when I fell. I turned the corner past an intersection and saw a slow pedestrian not far ahead. Rather than slow down, I tried to pass around a traffic light control box. Just as I did, I lost my footing and slapped down onto the concrete. I wasn’t badly hurt—just scrapes on my hands and an inexplicable shoulder bruise—but I was stunned. For just a moment, I stayed down, felt my body’s weight on the dirty sidewalk, leg hanging over the blacktop, head resting on concrete. Then I picked myself up, literally dusted myself off, and went on with my run.
Everyone falls, has fallen, will fall again.
Little kids—especially the really little ones—fall down all the time. Most of the time, they are fine. It can be hard to tell which falls they’ll happily toddle away from and which ones will require comforting and bandaids, and even those are usually unworrying in the end. When they have love and support, kids are resilient, mentally and physically. When I learned to ski in my 30s, I envied the little kids I shared the bunny hill with for their ability to fall hard and pop right back up unfazed. Learning to ski is a good way to reacquaint yourself with falling if you’re out of practice as a grownup.
Young children can achieve a kind of falling-drunk ecstatic state. I’ve seen it. Sometimes, when they’re playing at something that causes them to fall a lot, they’ll abandon the game and just start falling down for the sheer joy of it, spreading like contagion. Hurling themselves on the ground again and again, laughing uncontrollably, they fall every way they can imagine: tumbling headfirst, flopping like a ragdoll, sliding longways, jumping for hangtime, clutching each other to land in a pile.
Some unlucky kids get hurt in a fall, but I estimate that most don’t come to understand the potential for injury until they’re much older, maybe teens. By then, the simple geometry of bigger bodies makes falling a riskier proposition. I remember taking a couple of painful bumps at that age, but looking back now, it’s almost comical how quickly my body recovered from those injuries. They were painful enough to remember, but largely not serious enough to scar.
Most teenagers have gotten pretty good at the mechanical aspects of staying upright, which greatly mitigates one of the major reasons people fall. Falling at that age is usually the result of mental error. Kids largely figure out their bodies relatively early, dealing with the rest is the work of a lifetime.
A fortunate thing about middle age is that falling hasn’t yet taken on the grim implications it has for the elderly. Still, I’m somewhere on that road. Unless something else takes me out before I get there, it’s the destination I’ll eventually reach, where the prospect of a fall is persistent and life-threatening.
For now, at least, I’m fortunate enough to be able to get back up after a brief rest on the pavement. I’m still green enough to take bumps and learn from them, and in so doing avoid more dire falls later on. Scrapes and bruises (even inexplicable ones) don’t heal as fast as they used to. The little aches seem to last longer, too. But I’m on my feet, one after the other, picking up speed down the sidewalk. I’ll slow down before I go around the next signal box, and I’ll feel my feet steady-sure to the ground.
Paged Out! is, in its own words, an experimental (one article == one page) technical magazine about programming (especially programming tricks), hacking, security hacking, modern computers, electronics, demoscene, and other similar topics. I just got turned on to this, but I am really loving the most recent issue, Issue 7, which came out last month.
The Boston Public Library has posted digital copies of its M. C. Escher prints, and they are really something to behold. I remember a high school art project where my teacher, Mrs. Allard, asked the class to create something inspired by Escher. I did a transitional pen-and-ink pattern-filling based on Day and Night, and I’ve had a soft spot for his work ever since.
I have been thinking about game design a lot lately, so Raph Koster’s latest post, titled “Game design is simple, actually,” is very timely for me. Despite its trollish title, it covers a lot of ground laying out the complexities of game design, but in a very well structured way—better structured, in fact, than I think I’ve ever seen applied. There’s a ton of depth here; he’s not kidding when he says each of the 12 items could be (indeed, is) a whole shelf of books. I expect I’ll be returning to this for quite some time.
Imagery
Context-Free Patent Art: Probably more accurately “Patent Art Taken out of Context,” but close enough.
Is it me or do the issues from this complete collection of Swedish IKEA catalogs look way more interesting than the American versions of the same? At least the ones from the late 90s and early 2000s, which is when I would have seen them.
Adam Aleksic wrote recently on the similarities between the harms we popularly attribute to social media and those attributed to television. I grew up squarely in the midst of the moral panic that Baby Boomer parents felt over the malign influence of television on their children. No doubt influenced by their own tender years spent in front of the “boob tube,” there seemed to be endless hand wringing over not whether but how much TV would damage kids’ brains. I see the parallels between that shared freakout and today’s panic over the impact of social media, even as I harbor plenty of concern myself.
The first and most obvious parallel to me is that so much of the anxiety seems to be displaced from parents to children. That is, the young parents of the 70s and 80s represented the first generation of children who grew up with TV in the house expressing worry about its influence on their own children. It’s not hard to see how much of that concern seems motivated by fear of the damage their own exposure to television may have caused. Likewise, today’s young parents come from the first generation of social media users, and one way they are grappling with the harms they experienced is to express worry for their children. Like many parents, I’m not only trying to minimize my daughter’s exposure to social media, I’m also minimizing my own.
I think Aleksic’s notes on the similarities between TV and social media should prompt those of us who see the harms as distinct to be more clear about what those differences are. Two immediately come to mind for me:
The first is accessibility and ubiquity, as noted in his piece. The availability of social media on personal, portable, handheld devices greatly increases its reach, and its ability to send urgent-seeming notifications and alerts allows it to interrupt non-social media activities and colonize more of our time and attention. Television, much as its critics may have complained about its supposed inescapability, could never have such direct, immediate, and intrusive access to its viewers.
The other is the very tight feedback loop of individualized, algorithmic adjustments these apps use. Any individual TV channel was (and is) the same for all viewers. But modern social media apps learn from their users, reading both overt and subtle, implicit behavioral cues to shape their behavior. It’s critical to remember that social media apps are designed with a goal in mind—almost always to encourage more and more time and “engagement” in app—and are designed to achieve those goals by constantly tweaking the way they work. These adjustments can be so effective because they are based on a direct stream of individualized behavioral data (each user’s activity within the app), and they do not need to compromise their effectiveness by targeting more than one individual at a time. In other words, it poses no problem if the thing that would make your social media feed maximally engaging to you would be extremely distasteful to me, because I’ll never see your feed.
The propagandists of the mass media era had to develop grand theories of messaging and communication to underlie their efforts to manipulate public sentiment, because they could only address their messages to the collective public. (e.g., Propaganda by Edward Bernays) Modifying behavior through social media requires no larger framework to inform what works and what doesn’t. Its infinitely granular addressability and adaptability simply requires the diligence to conceive of and execute as many experiments as necessary to achieve the desired result, because the effectiveness of each can be easily and directly measured.
This effect is magnified by how much tighter the experimental iteration cycle is in the social media world than it is in television. In just a few seconds of scrolling through a feed, a social media app may run dozens of experiments to gauge a user’s engagement and adjust its behavior in real time. The amount of time it takes to produce a piece of television media, broadcast it, gather audience feedback, and incorporate changes into more content is better measured with a calendar than a stopwatch. And this means that even if each refinement has only a tiny effect, the overall impact is much greater because refinements can be made in much greater volume.
It is certainly instructive to consider modern attitudes toward technologies like social media in the context of earlier generations’ reactions to media innovation. It’s important to remember that, in their day, the invention of the novel and the spread of mass market paperback publication were both considered socially harmful by at least some concerned authorities. But it’s also important to identify what’s distinctive about new media technology and consumption, and to be able to articulate how those distinctions might represent new risks. It’s far harder to mitigate or manage unidentified risks than those we assume intentionally with good information.
With the state of American news media today being a very live concern, I was reminded of two films I saw a few years ago describing the production of news in another era. The two films were both produced by the Encyclopedia Britannica, whose film output was previously unknown to me, and both are named “Newspaper Story.” The first is from 1950 and describes a seemingly fictional local newspaper in a midwestern town. The second, from 1973, documents the production process of the Los Angeles Times.
I find both of these films fascinating. One reason is the approach to gathering and reporting on news described in these pieces, which strikes me as speaking for an optimistic American post-war media consensus, idealized and imperfect as it is. The other is the amount of effort that went into the physical production of the papers themselves. The advent of near-instantaneous digital communication completely restructured these enterprises and shifted media companies’ primary efforts away from what was previously the thrust of their work: producing some physical product, whether bundles of printed pages or towers that beam radio signals to receivers.
Both of these are great watches, but if you’re only going to watch one, I recommend the LA Times film from the 70s.
I already link to Bracket City, a daily word puzzle, from my links page. But I haven’t yet linked to the Bracket City Dispatch, the newsletter that for some reason hasn’t moved over to The Atlantic with its namesake game. It’s an interesting word-of-the-day newsletter. I’d really love to find something to replace the Paul McFedries’ old Word Spy newsletter, which focused on neologisms, but for now, this will do.
Speaking of daily puzzles, I recently discovered Doople, in which players find pairs of words that link together to build a chain. It’s a lot like Puzzmo’s Circuits, which came out just a month or two ago and uses the same core puzzle concept with a more variable structure.
They don’t make it (software) like they used to
I have seen a bunch of good essays and blog posts from technologists trying to grapple with the weaknesses of LLMs without sliding into facile dismissal or doomerism. One that really helped me with my own thinking on the matter is Why your boss isn’t worried about AI by Boyd Kane, which does a good job breaking down key ways LLMs don’t work the way software typically does. It’s hard to emphasize enough how important determinism is for programming, and the way LLMs rip away that assumption (possibly irrevocably so) is extraordinarily disorienting. But, as this piece lays out, that’s not the only assumption being broken.
The Great Software Quality Collapse: I look at this as a kind of companion piece to Boyd Kane’s essay. Even traditional, non-LLM software is going through a crisis of quality. It would be very difficult to argue that commercial software hasn’t become a profligate resource waster. The headline example in this essay, the MacOS calculator app leaking 32GB of memory, is a grievous example that should be a wake-up call for the industry. Not because of its cost—for better or worse, memory is cheap these days—but because of what it says about how the industry is failing to do quality work. Wasting 32GB of memory, especially for an app as simple as a desktop calculator, is hard, and actually shipping such an enormous flaw should make everyone think twice about how risky software is.
No seriously, they don’t make it like they used to
This charming little training film illustrates the way people thought about bringing computer technology into the enterprise almost 50 years ago. One of the bitterest ironies in the state of computing today is that there are still plenty of corners of the business world that could still benefit from adopting very basic information technology, but that’s not where the money is right now.