89 lines
2.3 KiB
Rust
89 lines
2.3 KiB
Rust
use std::any::type_name;
|
|
use std::fmt::Display;
|
|
pub use std::path::Path;
|
|
|
|
pub use color_eyre::eyre::{eyre, Report, Result};
|
|
pub use itertools::Itertools;
|
|
pub use lazy_static::lazy_static;
|
|
pub use regex::Regex;
|
|
pub use tracing::{debug, error, info, trace, warn};
|
|
use tracing_subscriber::EnvFilter;
|
|
|
|
pub trait Solution<Output1: Display, Output2: Display> {
|
|
fn day() -> String {
|
|
let mut day = String::from(type_name::<Self>().split("::").next().unwrap());
|
|
day.make_ascii_lowercase();
|
|
|
|
day.to_string()
|
|
}
|
|
|
|
fn new<P: AsRef<Path>>(pathname: P) -> Self;
|
|
|
|
fn part_1(&mut self) -> Output1;
|
|
fn part_2(&mut self) -> Output2;
|
|
|
|
fn get_sample(part: i32) -> String {
|
|
let possible_paths = [
|
|
format!("samples/{}.txt", Self::day()),
|
|
format!("samples/{}_{}.txt", Self::day(), part),
|
|
];
|
|
|
|
possible_paths
|
|
.into_iter()
|
|
.find(|p| Path::new(p).exists())
|
|
.expect("at least one sample should exist")
|
|
}
|
|
|
|
fn run(type_of_input: &str) -> 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 mut day = Self::new(format!("{}s/{}.txt", type_of_input, Self::day()));
|
|
|
|
info!("Part 1: {}", day.part_1());
|
|
info!("Part 2: {}", day.part_2());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn main() -> Result<()>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
Self::run("input")
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! test_sample {
|
|
($mod_name:ident, $day_struct:tt, $part_1:expr, $part_2:expr) => {
|
|
#[cfg(test)]
|
|
mod $mod_name {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_part_1() {
|
|
let path = $day_struct::get_sample(1);
|
|
let mut day = $day_struct::new(path);
|
|
assert_eq!(day.part_1(), $part_1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_part_2() {
|
|
let path = $day_struct::get_sample(2);
|
|
let mut day = $day_struct::new(path);
|
|
assert_eq!(day.part_2(), $part_2);
|
|
}
|
|
}
|
|
};
|
|
}
|