//! 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; /// 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( 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 { let (part_1, part_2) = ((self.part_1_fn)(data)?, (self.part_2_fn)(data)?); Ok(Self { part_1, part_2, ..self }) } }