106 lines
2.7 KiB
Rust
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
|
|
})
|
|
}
|
|
}
|