use std::fmt::Display; use std::path::Path; use color_eyre::eyre::Result; use tracing::info; use tracing_subscriber::EnvFilter; pub trait Solution<Input, Output: Display> { fn day() -> &'static str; fn parse_input<P: AsRef<Path>>(pathname: P) -> Input; fn part_1(input: &Input) -> Output; fn part_2(input: &Input) -> Output; fn main() -> Result<()> where Self: Sized, { tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env()) .with_target(false) .with_file(true) .with_line_number(true) .without_time() .compact() .init(); color_eyre::install()?; let input = Self::parse_input(format!("inputs/day{}.txt", Self::day())); info!("Part 1: {}", Self::part_1(&input)); info!("Part 2: {}", Self::part_2(&input)); Ok(()) } } #[macro_export] macro_rules! test_sample { ($mod_name:ident, $day_struct:tt, $part_1:expr, $part_2:expr) => { #[cfg(test)] mod $mod_name { use lazy_static::lazy_static; use super::*; lazy_static! { static ref SAMPLE: Input = $day_struct::parse_input(&format!("samples/day{}.txt", $day_struct::day())); } #[test] fn test_part_1() { assert_eq!($day_struct::part_1(&SAMPLE), $part_1); } #[test] fn test_part_2() { assert_eq!($day_struct::part_2(&SAMPLE), $part_2); } } }; }