advent-of-code-rust-runner

Crates.ioadvent-of-code-rust-runner
lib.rsadvent-of-code-rust-runner
version0.2.0
created_at2025-12-01 20:38:30.701691+00
updated_at2025-12-01 20:38:30.701691+00
descriptionRust framework for running Advent of Code solutions
homepage
repositoryhttps://github.com/ThePants999/advent-of-code-rust-runner
max_upload_size
id1960604
size76,561
Chris Paterson (ThePants999)

documentation

README

Advent of Code Runner for Rust

This crate is a simple framework library to help you focus on solving Advent of Code puzzles instead of wiring up input handling and timing. It:

  • Downloads your input from the AoC website using your session cookie and caches it locally.
  • Lets you provide optional example inputs/answers so your solution is automatically tested.
  • Runs your solutions with simple CLI flags, and measures per-part timings (with optional multi-run stats).

Quick start

  1. Add the dependency - and a log-compatible logger. Note, the crate re-exports anyhow::Result and anyhow::Context, so downstream crates can use Result/Context without adding an anyhow dependency, but you might want to add the dependency anyway if you need other features like anyhow::bail!().
[dependencies]
advent-of-code-rust-runner = "0.2"
log = "0.4"
env_logger = "0.11"
  1. Implement each day by defining a type that implements DayImplementation. Outputs are stored/logged as strings, but your Output type can be any Display + Eq type (e.g., i64, String, or &str).
use advent_of_code_rust_runner::{DayImplementation, Result};

pub struct Day01;

impl DayImplementation for Day01 {
    type Output<'a> = &'a str;
    type Context<'a> = ();

    fn day(&self) -> u8 { 1 }

    fn execute_part_1<'a>(&self, input: &'a str) -> Result<(Self::Output<'a>, Self::Context<'a>)> {
        let words: Vec<&'a str> = input.split_whitespace().collect();
        Ok((words[0], ()))
    }

    fn execute_part_2<'a>(&self, input: &'a str, _ctx: Self::Context<'a>) -> Result<Self::Output<'a>> {
        let words: Vec<&'a str> = input.split_whitespace().collect();
        Ok(words[1])
    }
}
  1. If you want, you can also pass context between your part 1 and part 2 implementations by specifying the type and returning it from your part 1 function, e.g. to avoid re-parsing the input.
pub struct Day01Context<'a> {
    words: Vec<&'a str>,
}

impl DayImplementation for Day01 {
    type Output<'a> = &'a str;
    type Context<'a> = Day01Context<'a>;

    fn day(&self) -> u8 { 1 }

    fn execute_part_1<'a>(&self, input: &'a str) -> Result<(Self::Output<'a>, Self::Context<'a>)> {
        let words: Vec<&'a str> = input.split_whitespace().collect();
        Ok((words[0], Day01Context { words }))
    }

    fn execute_part_2<'a>(&self, _input: &'a str, ctx: Self::Context<'a>) -> Result<Self::Output<'a>> {
        Ok(ctx.words[1])
    }
}
  1. You can also optionally provide the example input/answers to enable built-in tests.
impl DayImplementation for Day01 {
    fn example_input(&self) -> Option<&'static str> { Some("hello world") }
    fn example_part_1_result(&self) -> Option<Self::Output<'static>> { Some("hello") }
    fn example_part_2_result(&self) -> Option<Self::Output<'static>> { Some("world") }
}
  1. In main, register your days and run the runner:
use advent_of_code_rust_runner::{Runner, Day};
use env_logger;

mod day01;

fn main() {
    env_logger::init();
    let days: Vec<Box<dyn Day>> = vec![Box::new(day01::Day01 {})];
    let runner = Runner::new("2025", days).expect("runner init");
    runner.run(); // parses CLI args and exits on completion/failure
}

Command-line flags

  • -d, --day <n>: Run a specific day (1–25, or 1–12 for years >= 2025).
  • -a, --all: Run all registered days.
  • -k, --skip-tests: Skip example tests; run only real inputs.
  • -t, --tests-only: Run only example tests.
  • -s, --stats <n>: Run each part n times (>=1) and show min/median/mean/max times.
  • -h, --help: Show usage (from clap).

By default (no -d/-a), the runner tries to infer “today” in AoC time (UTC−5) during December of the configured year.

Input handling

On first run, you’ll be prompted for your AoC session cookie value. It’s saved to ./session, and inputs are cached under ./inputs/dayXX. Add both to .gitignore if you’re committing your solutions.

Commit count: 0

cargo fmt