This is advent_of_code_traits
, a set of traits to implement solutions to Advent of Code in Rust.
It takes a trait-based approach using const-generics and autoderef specialization.
It's basically an excuse to play with rust's type system.
This is already serviceable, but there will be frequent breaking changes as the traits are improved and refined.
The "plan" is to release a stable version in time for December 2021 when it's ready.
See the Changelog for a current view of progress.
Please see also the examples.
Implement traits with your solutions to each Day of Advent of Code.
use advent_of_code_traits::{days::*, MissingPartTwo, Part1, Part2, ParseInput, run, Solution, SolutionRunner};
pub struct AdventOfCode2021<const DAY: u32>;
impl Solution<'_, Day25, Part1> for AdventOfCode2021<Day25> {
type Input = Vec<u32>;
type Output = u32;
fn solve(&self, input: &Self::Input) -> Self::Output {
// your solution to Part1 here...
}
}
That's how we solve the solution given a nicely typed Vec<u32>
, but Advent of Code gives us plaintext input.
So first we need to parse the input...
// ..continued from above
impl ParseInput<'_, Day25, Part1> for AdventOfCode2021<Day25> {
type Parsed = Vec<u32>; // <-- the input type fed to Solution::solve
fn parse_input(&self, input: &'_ str) -> Self::Parsed {
input
.lines()
.map(|s| s.parse().expect("invalid integer"))
.collect()
}
}
To run only Part1 of a day of Advent of Code, you currently need to impl MissingPartTwo
to help disambiguate the specialization:
impl MissingPartTwo<Day25> for AdventOfCode2021<Day25> {}
If you don't do this (and haven't implemented Solution for Part2) you'll see an error like:
the method `run` exists for reference `&&&AdventOfCode2021<25_u32>`, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
`AdventOfCode2021<25_u32>: MissingPartTwo<25_u32>`
which is required by `AdventOfCode2021<25_u32>: SolutionRunner<25_u32, 1_u16>`rustcE0599
Here comes the part where we actually run our solution!
let input = std::fs::read_to_string("./input/2021/day25.txt").expect("failed to read input");
run!(AdventOfCode2021::<Day25>, &input);
This reads input from a file and passes it to your struct to parse and then solve.
It will print the output of your solution (which must impl Debug
).
run!
is currently a humble macro_rules!
declarative macro and is very simple.
It's main purpose is to veil the use of autoderef specialization.
Please refer to the examples for more demonstrations.
Because the Solution
and ParseInput
traits are generic over const DAY: u32
you are free to implement them many times for the same struct.
The compiler will only yell at you if you implement them for the same DAY twice (as it should!).
Day1
is used in the examples (because it looks awesome in my humble opinion). It is simply 1_u32
.
advent_of_code_traits::days
looks like this:
mod days {
pub const Day1: u32 = 1;
pub const Day2: u32 = 2;
// ...
pub const Day25: u32 = 25;
}
Solution
and ParseInput
are also generic over const PART: u8
which works very similarly to DAY.
See the specialization module's docs.
I am very grateful for @gobanos' cargo-aoc which was a huge inspiration while creating this.
This crate is no match for the convenience or ease of use of cargo-aoc.
Having said that, I hope it brings something new to the table (faster compile times perhaps?) and that others enjoy using this half as much as I enjoyed using cargo-aoc.
I have used cargo-aoc for all of my Advent of Codes in Rust before 2021, and it is a brilliant, crazy use of procedural macros.
Thank you Gobanos! :)
Contributions are welcome, please see CONTRIBUTING
Please also see ARCHITECTURE for a guided tour of sorts of the code base.
I might take a long time to merge/release your contributions, I'm still inexperienced at the whole open source mainenance thing. I am grateful for them though.
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in advent_of_code_traits by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.