/Advent-of-Code-Helper

An Emacs Lisp library to aid in downloading Advent of Code input

Primary LanguageEmacs LispGNU General Public License v3.0GPL-3.0

Advent of Code Helper

Introduction

(Note: when viewing this README in Emacs, Org help: links will be activated for some of the Elisp functions and variables mentioned.)

This is a small library intended to make interacting with the Advent of Code website more programmatic. This library is inspired by

In 2023, I decided to give Advent of Code a few rounds. I thought it would be nice to automate downloading and submitting puzzle solutions (I must’ve come across mentions or examples of this automation previously, but I don’t quite remember what the initial inspiration was.)

I then began looking for tools in Emacs for this, and found (among possibly others) the two projects mentioned above. I’m not sure why at this point, but despite the existence of these other projects, I decided to write my own. 🤷

I decided to go with an EIEIO based implementation, in particular because I liked the idea of its customization buffers, which create an eclectic bridge closing the gap between user interaction and some obfuscated piece of data that lives in memory.

It also looks like there are already some awesome attempts at writing full-blown Advent of Code GUIs (in the form of things like web apps) which look like sources of further inspiration:

Background

From the Advent of Code website:

Advent of Code is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like. People use them as interview prep, company training, university coursework, practice problems, a speed contest, or to challenge each other.

In order to play Advent of Code, you need to set up an account with it and log in. You then solve the available puzzles for a given year. In order to do so, you first need to download that puzzle’s input, which is what you’ll work with to solve the puzzle.

Normally, you would download this input manually, specifying where it should be downloaded onto disk. However, it’s possible to programmatically pull it down to local storage, as long as your login cookie hash, inspectable via your browser’s development tools, is loaded into Emacs. See url-cookie-list.

This library provides a few utilities for facilitating these concerns:

  • Setting the cookie’s hash.

    We refer to this as “bootstrapping” the cookie.

  • Downloading the puzzle input into a particular directory.

    This directory is created automatically if missing.

  • Visiting a particular puzzle directory.

    This obviates the need to remember where you have your Advent of Code work stored.

  • Recording, and possibly submitting, a solution.

    In case you’ve completed a certain Advent of Code puzzle already, resubmitting it would be superfluous. But you may still want to record an existing solution with this app.

Installation

To install:

  1. Put advent-of-code-helper.el somewhere in your Emacs load-path and require it.
  2. Activate the minor mode: M-x advent-of-code-helper-mode (which see). This adds an Advent-of-Code top-level menu.

Usage

Bootstrapping

When first using this package, you need to record your cookie’s hash. You can run the advent-of-code-helper-bootstrap command directly, or select Bootstrap Cookie from the menu (which runs this command for you.)

Preparing a Puzzle

This is perhaps best illustrated with an example. Say you want to work on Day 1 of Year 2016. Select Prepare Puzzle from the menu (which runs advent-of-code-helper-prepare-puzzle). Follow the minibuffer prompts asking you for the year (2016) and day (1).

If non-existent, the directory 2016/day/1 is created under your advent-of-code-helper-top-level-directory, for example, ~/adventofcode/2016/day/1. Note that this scheme intentionally mimics the slugs used by the Advent of Code website itself.

After possibly creating the needed directory, the input for 2016 Day 1 is downloaded there, as input.txt.

Visiting a Puzzle

This is provided as a convenience for visiting a puzzle directory in Dired, given that one only cares to remember its year and day, and not the details of where it’s stored.

Select Visit Puzzle from the menu (advent-of-code-helper-visit-puzzle).

Submitting a Puzzle Answer to Advent of Code

Within a puzzle directory, two new submenus appear under the main menu: Part 1 Actions and Part 2 Actions.

For example, let’s assume you’ve completed Year 2023 Day 1, and you want to submit it. While in any buffer visiting a file in that directory (for example, your solution file, the Dired buffer visiting that directory, etc.) select Part 1 Actions, and then Record/Submit.

When selecting Record/Submit, the solution field is pre-populated with any active-region text. This eliminates the need to, for example, copy and paste your solution: you simply highlight it, then do Record/Submit.

Along these lines, it’s recommended to enable context-menu-mode, so that, assuming you’ve written down your solution in a buffer, you can double-click it to highlight it, then left-click anywhere in the buffer to get a context-menu where you can access the Advent of Code Helper main menu.

The EIEIO customization buffer provides a toggle-option for uploading your submission to Advent of Code (which is the default), or else only recording your solution locally. When submitting, your solution is still recorded locally.

After submitting, the HTTP response buffer is rendered by EWW and presented.

Customizing

Currently, a few Customize options are included, mainly for advent-of-code-helper-top-level-directory.

Room for Improvement

I haven’t gone about solving a great deal of Advent of Code puzzles with this app just yet. I’m sure ideas will come to me as I do this.

  • Let the user record whether an answer was too high, too low, or otherwise incorrect.

    Maybe we’d want to search the EWW buffer for a phrase like “Your answer was too high.”, and set this field automatically.

  • Integration with the user’s solution code itself.

    Following the idea of the first todo, an ERT test can query the recorded solution (currently something like part1.eieio) to test whether the current solution iteration still yields an answer that is, for example, still too high (because it equals or exceeds the current too-high answer.)