8 releases

0.0.9 Dec 2, 2023
0.0.8 Dec 1, 2023
0.0.7 Jul 15, 2023
0.0.3 Jun 22, 2023
0.0.1 Feb 11, 2023

#186 in Development tools

MIT license

78KB
2K SLoC

aocli

Crates.io Downloads License

A helper CLI tool for solving Advent of Code in Rust. Uses aoclib to parse inputs and run solutions.

Installation

cargo install aocli

The binary name for aocli is aoc.

Requirements

  • cargo is in PATH
  • terminal with ANSI colour support

Features

  • download puzzle inputs and past puzzle answers
  • submit puzzle answers
  • cache puzzle answers locally for testing
  • run solutions on many different inputs
  • run solutions to all days, or specified days, of a year
  • time solutions
  • parse puzzle inputs with aoclib
  • quickly view progress
  • open year or day webpage in browser
  • project management (create workspace, crates and files)
  • minimal source files per day (only one line of boilerplate)
  • minimal compile times per day (separate crates that share dependencies)

Example

Functionality

A solution workspace consists of the root directory, year directories, and day directories. For example:

aoc
├── aoc-root
├── Cargo.toml
├── Cargo.lock
├── .session
├── .gitignore
├── target
├── 2015
│   ├── 01
│   └── 02
├── 2016
│   └── 01
└── 2017
    ├── 01
    ├── 02
    └── 03

Here, the root directory (a Cargo Workspace) is called aoc and contains year directories 2015, 2016 and 2017, which each contain various day directories. The path to 2015 day 1 is /aoc/2015/01 and the path to 2017 day 3 is /aoc/2017/03. Each day directory is a regular Rust binary crate. The aoc-root file denotes the root of a solution workspace, and the .session file contains the session cookie to log into the Advent of Code site.

aocli commands may work from within any of the three directory levels, and the required arguments and functionality may differ for each level. For example, the following three commands will do the same thing:

/aoc > aoc run 15 1
/aoc/2015 > aoc run 1
/aoc/2015/01 > aoc run

while the following two commands will run every solution for the year 2015 instead of just day 1:

/aoc > aoc run 15
/aoc/2015 > aoc run

Solutions

A solution to a day consists of a call to aoc::parts! from aoclib and a function for each solved part.

The input is passed in as an instance of aoc::Input from aoclib. See the docs for more information on how to use it.

For example:

aoc::parts!(1, 2);

fn part_1(input: aoc::Input) -> impl ToString {
    // solution to part 1
}

fn part_2(input: aoc::Input) -> impl ToString {
    // solution to part 2
}

However, aoc::parts!(), aoc::parts!(1) or aoc::parts!(2) may instead be used depending on which parts are implemented. The functions can return any type that is ToString, and the conversion to a String is not included in the timing of the solution.

Inputs

In addition to being a Rust binary crate for the solution, each day directory contains the day's puzzle input(s) and corresponding puzzle answers. Your actual puzzle input is named actual, but you may create other inputs and answers, such as for the examples on the site.

The file system structure looks like this:

DAY
├── Cargo.toml
├── src/DAY.rs
└── data
    ├── actual
    ├── example1
    └── example2

while each input directory contains the puzzle input and answers:

example1
├── input
├── 1
│   └── answer
└── 2
    └── answer

Empty or non-existent answer files are taken to mean that the answer is unknown.

add example1 would create the directories and empty files for example1 as above, to be filled in as desired.

get would create and fill in the actual input directory from the website.

run example1 would run the solution using the input example1.

run defaults to using the input actual.

Interpreting the output

run, debug, test and submit display puzzle answers colour-coded. Green means correct, red means incorrect, and yellow means the correct answer is not known.

Notes

In order to use the network features of aocli (get, submit and progress), you must paste your session cookie into the .session file created by this command, with or without the session= header.

If you create a crate as a dependency, such as for the Intcode computer in 2019, you must remember to add it to the Cargo Workspace by modifying the Config.toml file at the root.

Commands

Note that parameters surrounded by <> are required, while those surrounded by [] are optional.

init

Initialises a solution workspace in the current directory. For example:

/aoc > aoc init

will set up a solution workspace with aoc as the root directory, and it will attempt to call git init. It will also initialise a Cargo Workspace.

open (o)

/root > aoc open <YEAR>
/root/YEAR > aoc open
/root > aoc open <YEAR> <DAY>
/root/YEAR > aoc open <DAY>
/root/YEAR/DAY > aoc open

Opens the webpage for the year or day in the default browser using webbrowser.

new (n)

/root > aoc new <YEAR> <DAY>
/root/YEAR > aoc new <DAY>

Creates the directories, files and Rust crate for the solution to a new day of Advent of Code. Adds the new crate as a member of the Cargo Workspace.

get (g)

/root > aoc get <YEAR> <DAY>
/root/YEAR > aoc get <DAY>
/root/YEAR/DAY > aoc get

Downloads the puzzle input and any existing puzzle answers for the day from the website if they are not already in local files.

add (a)

/root > aoc add <YEAR> <DAY> <INPUT>
/root/YEAR > aoc add <DAY> <INPUT>
/root/YEAR/DAY > aoc add <INPUT>

Creates the directories and empty files for a new puzzle input called <INPUT>.

The name of the input must be a valid directory name, and cannot be 1 or 2.

clean

/root > aoc clean <YEAR>
/root/YEAR > aoc clean
/root > aoc clean <YEAR> <DAY>
/root/YEAR > aoc clean <DAY>
/root/YEAR/DAY > aoc clean

Resets the input and answer files to empty files within the actual input of every day of the year, or the specified day, so that get can fill them in.

run (r)

/root > aoc run <YEAR>
/root/YEAR > aoc run

Runs the solution to both parts of every day of the year with the actual puzzle input in release mode, providing total and average time statistics.

/root > aoc run <YEAR> <DAY> [INPUT] [PART]
/root/YEAR > aoc run <DAY> [INPUT] [PART]
/root/YEAR/DAY > aoc run [INPUT] [PART]

Runs the solution to the day in release mode.

Defaults to running both parts using the actual input, but a different input, or a specific part, can be provided.

For example:

/root/YEAR/DAY > aoc run example

to run both parts with input example,

/root/YEAR/DAY > aoc run 1

to run just part 1 with input actual, and

/root/YEAR/DAY > aoc run example 2

to run just part 2 with input example.

Note that the lack of flags here is why 1 and 2 are invalid names for inputs.

debug (d)

/root > aoc debug <YEAR> <DAY> [INPUT] [PART]
/root/YEAR > aoc debug <DAY> [INPUT] [PART]
/root/YEAR/DAY > aoc debug [INPUT] [PART]

The same as run, except the solution is run in debug mode instead of release mode.

run days (r d)

/root > aoc run <YEAR> days <DAYS>
/root/YEAR > aoc run days <DAYS>

Runs the solution to both parts of the specified days of the year with the actual puzzle input in release mode, providing total and average time statistics.

The <DAYS> argument should be a sequence of space-separated terms, where each term is one of the following:

  • a day, X
  • an inclusive range of days, X..Y
  • a negation of the above, -X or -X..Y

The start and end days in a range are optional, so X.. is equivalent to X..25 and ..Y is equivalent to 1..Y.

If the first term is a regular term, initially no days are included, and if the first term is a negated term, initially all days are included. Terms are then applied in order, one by one. A regular term causes its day(s) to be included, and a negated term causes them to be excluded.

  • days 4 8 = days 4..8 -5 -6 -7 = days 4..8 -5..7 = days ..8 -5..7 -..3
  • days -3 = days 1..25 -3 = days 1 2 4..
  • days -1 -25 = days 2..24

For example:

/root > aoc run 2019 days -25

to run all but day 25 in 2019,

/root/2021 > aoc run days -19

to run all but day 19 in 2021,

/root/2022 > aoc run days ..10 20..

to run days 1 to 10 and 20 to 25 in 2022, and

/root/2018 > aoc run days 1 4 9

to run days 1, 4 and 9 in 2018.

test (t)

/root > aoc test <YEAR>
/root/YEAR > aoc test

Runs the solution to both parts of every day of the year with every puzzle input in release mode.

/root > aoc test <YEAR> <DAY> [PART]
/root/YEAR > aoc test <DAY> [PART]
/root/YEAR/DAY > aoc test [PART]

Runs the solution to both parts, or a specific part, of the day with every puzzle input found in /DAY/data in release mode.

test days (t d)

/root > aoc test <YEAR> days <DAYS>
/root/YEAR > aoc test days <DAYS>

Runs the solution to both parts of the specified days of the year with every puzzle input in release mode.

The rules governing the argument <DAYS> are the same as in run days above.

submit (s)

/root > aoc submit <YEAR> <DAY> [ANSWER]
/root/YEAR > aoc submit <DAY> [ANSWER]
/root/YEAR/DAY > aoc submit [ANSWER]

Submits a puzzle answer to the next unsolved part of the day on the Advent of Code website.

The puzzle answer submitted will be the argument [ANSWER] if provided, or the last answer produced by the solution.

For example:

/root/YEAR/DAY > aoc run
/root/YEAR/DAY > aoc submit

will run the solution and then submit the answer it produced to the site.

progress (p)

/root > aoc progress
/root > aoc progress <YEAR>
/root/YEAR > aoc progress

Displays your account's progress in all years, or the specified year.

/root > aoc progress <YEAR> <DAY>
/root/YEAR > aoc progress <DAY>
/root/YEAR/DAY > aoc progress

Displays your account's correctly submitted answers to the day.

help

Opens this README.md in the default web browser.

Dependencies

~6–16MB
~198K SLoC