Advent Of Code

This is a small framework to help with Advent of Code by managing inputs, tests and boilerplate code while you focus on problem solving in a TDD fashion.

Installation

Install the library

This framework is distributed as a library as it consists mostly of mix tasks. You may add the dependency to your project, or add it to a new project created with mix new my_app.

defp deps do
  [
    {:aoc, "~> 0.11"},
  ]
end

Configuration

If it does not exist, create a configuration file in your application:

mkdir -p config
touch config/config.exs

Then add the following configuration:

import Config

# The prefix is used when creating solutions and test modules with
# `mix aoc.create`.
config :aoc, prefix: MyApp

Install your cookie

Retrieve your cookie from the AoC website (with you browser developer tools) and write the session ID in $HOME/.adventofcode.session. It should be a long hex number like 53616c7465645f5f1d5792d97e3370392425dea84ca4653bd9a083f164ecd92278bef5b6bd50...

Use the commands

The following commands use the default year and day based on current date. It is possible to override the defaults with the mix aoc.set command, or provide the --year and --day options.

Defaults management commands

The mix aoc.set command allows to set the default year and day. Those values are used by default when other commands are not called with --year or --day options.

This is useful when working on a problem from a previous year, or when you finish the last days after December 25th, so your CLI history or bash scripts can just call mix aoc.test or mix aoc.run without options.

Writing solutions

The mix aoc.create command will generate modules with the boilerplate code to be called by mix aoc.run and the generated tests.

defmodule MyApp.Y23.Day1 do
  alias AoC.Input

  def read_file(file, _part) do
    # Return each line
    Input.stream!(file, trim: true)
    # Or return the whole file
    # Input.read!(file)
  end

  def parse_input(input, _part) do
    input
  end

  def part_one(problem) do
    problem
  end

  def part_two(problem) do
    problem
  end
end

To call your code manually, you may use the following code:

solution_for_p1 =
  "path/to/input/file"
  |> MyApp.Y23.Day1.read_file(:part_one)
  |> MyApp.Y23.Day1.parse_input(:part_one)
  |> MyApp.Y23.Day1.part_one()

The generated tests will also call those functions one by one, so you can debug and assert each part separately.

The different callbacks are: