Skip to main content

A CLI for working with Advent of Code (AOC) problems

Project description

Automating your Advent of Code (AOC) Workflow: aoctools


aoctools is a command line interface (cli) that helps you automate Advent of Code (AOC) boilerplate, e.g., downloading the day's problem input and writing python boilerplate.


Step 0: Install

pip3 install aoctools

Step 1: Initialize a project

usage: aoctools init [-h] root_path year

positional arguments:
  root_path   the root project directory

The init command will create an aoctools project at the path that you specify.

Step 2: Bootstrap the boilerplate for a new day

Make sure that you set an environment variable named AOC_SESSION_COOKIE to the session cookie of your AOC login; in Chrome, you can obtain this cookie by opening Developer Tools (View > Developer > Developer Tools), opening the Application tab, and looking for the value that appears next to session.

As an alternative to setting this variable every time that you run the tool, aoctools supports .env files. You can create a .env file under your project directory and run aoctools from said directory for an even more ergonomic workflow. NB: .env files are loaded relative to the working directory (where you run aoctools from) - not the project directory.

usage: aoctools init_day [-h] [--root-path [ROOT_PATH]] [--year YEAR]
                         [--skip-bootstrap] [--skip-download]
                         [--session-cookie SESSION_COOKIE]

positional arguments:
  day                   aoc challenge day

optional arguments:
  -h, --help            show this help message and exit
  --root-path [ROOT_PATH]
                        the root project directory; defaults to the current
                        working directory
  --year YEAR           aoc challenge year; defaults to the project year
  --skip-bootstrap      don't generate python boilerplate
  --skip-download       don't download the challenge input data
  --session-cookie SESSION_COOKIE
                        an AOC login session cookie; defaults to the
                        environment variable AOC_SESSION_COOKIE

If you want to generate boilerplate for the challenge day without downloading the day's input file, pass --skip-download to the aoctools init_day command; you can download the day's input file later by passing --skip-bootstrap; NB: the init_day command will not clobber existing python files, so running it twice without passing --skip-bootstrap will fail.

Step 3: Hack

Bootstrapping will generate a new module under the root aoc module named after the freshly bootstrapped day. For example, running aoctools init_day 1 will create a file named aoc/d01/ containing:

from typing import IO

def p_1(input_file: IO,
        debug=False): # pylint: disable=unused-argument

def p_2(input_file: IO,
        debug=False): # pylint: disable=unused-argument

Filling in p_1 and p_2 is where you come in; aoctools requires that you return a (stringifiable) value if you want to use the built-in solution printer and regression test framework, but there are no restrictions beyond that.

Running your solution with aoctools will result in p_1 or p_2 being called with a reference to the input file; semantically, it's the same as if you had written:

import aoc.d01

if __name__ == '__main__':
    with open('data/d01/input.txt', 'r', encoding='utf8') as input_file:
        aoc.d01.p_1(input_file, False) # or True

and run the file from the root of your project directory. The debug variable is set via the cli and makes it easy to control print output:

def p_1(input_file: IO, debug=False):
    v_1 = 1
    v_2 = 2

    if debug:
        print(f"v_1 + v_2 = {v_1} + {v_2} = {v_1 + v_2}")

    return v_1 + v_2

Step 4: Test the example inputs

Create a new example by running the init_example command:

usage: aoctools init_example [-h] [--root-path [ROOT_PATH]]
                             day {1,2} expected [example_number]

positional arguments:
  day                   aoc challenge day
  {1,2}                 the challenge part for the example
  expected              the expected example value
  example_number        aoc challenge day; optional (autoincrement)

optional arguments:
  -h, --help            show this help message and exit
  --root-path [ROOT_PATH]
                        the root project directory; defaults to the current
                        working directory

Examples are created in data/day/example_n.txt. By default, your examples will be numbered sequentially; you can specify a number explicitly by passing an additional [example_number] argument.

Example files take the form:

part: 1
expected: 2

1-3 a: abcde
1-3 b: cdefg
2-9 c: ccccccccc

The first line must be part: (1|2) corresponding to the part of the AOC problem that the example pertains to. The second line must be an expected value: expected: (.+). The third line must be blank line. The rest of the file should contain the example text.

Run examples via the run_examples command:

usage: aoctools run_examples [-h] [--root-path [ROOT_PATH]] [--debug]
                             day [example_number]

positional arguments:
  day                   aoc challenge day
  example_number        the example to run; defaults to all examples

optional arguments:
  -h, --help            show this help message and exit
  --root-path [ROOT_PATH]
                        the root project directory
  --debug               print debug info

You must specify a day. You can optionally specify a specific example to run; by default, all examples for the given day will run.

Step 5: Run your solution

usage: aoctools run [-h] [--root-path [ROOT_PATH]] [--debug] day {1,2}

positional arguments:
  day                   aoc challenge day
  {1,2}                 the challenge part to run

optional arguments:
  -h, --help            show this help message and exit
  --root-path [ROOT_PATH]
                        the root project directory
  --debug               print debug info

As an example, you can run Day 1, Pt 1 from your root project directory by invoking:

aoctools run 1 1

solution to day 1, part 1: xxxx

Step 6 (Optional): Regression tests & Code Quality

Once you identify a solution you can populate the automatically generated regression tests under tests/aoc/test_d*:

import aoc.d01

from tests.aoc.test_base import BaseTestCase

class TestAll(BaseTestCase):
    def test_part_one(self):
        self.run_aoc_part(1, CHANGEME, aoc.d01.p_1)

    def test_part_two(self):
        self.run_aoc_part(1, CHANGEME, aoc.d01.p_2)

Running make test from the root project directory will run all regression tests.

Similarly, running make lint will type lint and type check your code and tests with both pylint and mypy.

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aoctools-0.2.0.tar.gz (10.0 kB view hashes)

Uploaded source

Supported by

AWS AWS Cloud computing Datadog Datadog Monitoring Facebook / Instagram Facebook / Instagram PSF Sponsor Fastly Fastly CDN Google Google Object Storage and Download Analytics Huawei Huawei PSF Sponsor Microsoft Microsoft PSF Sponsor NVIDIA NVIDIA PSF Sponsor Pingdom Pingdom Monitoring Salesforce Salesforce PSF Sponsor Sentry Sentry Error logging StatusPage StatusPage Status page