1
Fork 0
advent-of-code/source/solution.rs

106 lines
2.7 KiB
Rust

//! Functionality for [`Day`]s and [`Solution`]s.
use {color_eyre::Result, derivative::Derivative};
/// The information for an advent day of a given year.
#[derive(Debug)]
pub struct Day {
/// The advent day.
pub day: i32,
/// The year for the advent.
pub year: i32,
}
impl Day {
/// Create a new [`Day`] from a given day and year.
pub fn new(day: i32, year: i32) -> Self {
Self { day, year }
}
/// Return the filter string as `YEAR::DAY` for this day.
pub fn filter_string(&self) -> String {
format!("{}::{:02}", self.year, self.day)
}
/// Return the link for this day on the Advent of Code website.
pub fn day_link(&self) -> String {
format!("{}/day/{}", self.year_link(), self.day)
}
/// Return the link for this year on the Advent of Code website.
pub fn year_link(&self) -> String {
format!("https://adventofcode.com/{}", self.year)
}
}
/// Function type alias for the expected input and outputs of a day.
pub type DayFunction = fn(input: &str) -> Result<String>;
/// The solution to one of the advent calendar days.
#[derive(Derivative)]
#[derivative(Debug)]
pub struct Solution {
/// Which day the solution applies to.
pub day: Day,
/// The calculated result for part one.
pub part_1: String,
/// The calculated result for part two.
pub part_2: String,
/// The expected result for part one (for validation).
pub part_1_expected: String,
/// The expected result for part two (for validation).
pub part_2_expected: String,
/// The function for part one.
#[derivative(Debug = "ignore")]
pub part_1_fn: DayFunction,
/// The function for part two.
#[derivative(Debug = "ignore")]
pub part_2_fn: DayFunction,
}
impl Solution {
/// Create a new [`Solution`] with a given [`Day`] and two [`DayFunction`]s.
pub fn new(day: Day, part_1_fn: DayFunction, part_2_fn: DayFunction) -> Self {
Self {
day,
part_1: String::new(),
part_2: String::new(),
part_1_expected: String::new(),
part_2_expected: String::new(),
part_1_fn,
part_2_fn,
}
}
/// Helper function to add the expected results for both parts.
pub fn with_expected<A: std::fmt::Display, B: std::fmt::Display>(
self,
part_1_expected: A,
part_2_expected: B,
) -> Self {
Self {
part_1_expected: format!("{part_1_expected}"),
part_2_expected: format!("{part_2_expected}"),
..self
}
}
/// Run the [`DayFunction`]s for this [`Solution`] and put the results in
/// their respective fields.
pub fn solve(self, data: &str) -> Result<Self> {
let (part_1, part_2) = ((self.part_1_fn)(data)?, (self.part_2_fn)(data)?);
Ok(Self {
part_1,
part_2,
..self
})
}
}