use crate::Aoc;
use std::marker::PhantomData;
use std::time::Instant;
use anyhow::Result;
use crate::input::get_input;
use crate::parser::Parsing;
pub trait Solvable {
fn run(&self, aoc: &Aoc) -> Result<()>;
fn day(&self) -> u8;
}
pub struct Solution<P, S, I, O: std::fmt::Display>
where
P: Parsing<I>,
S: Fn(I) -> O,
{
pub day: u8,
pub parser: P,
pub solver: Solver<S, I, O>,
}
impl<P, S, I, O: std::fmt::Display> Solvable for Solution<P, S, I, O>
where
P: Parsing<I>,
S: Fn(I) -> O,
{
fn run(&self, aoc: &Aoc) -> Result<()> {
let input = get_input(aoc, self.day)?;
print!(
"Day {} - {} with {}: ",
self.day,
self.solver.name,
self.parser.name()
);
let parse_start = Instant::now();
let parsed_input = self.parser.run(&input);
let parse_end = Instant::now();
match parsed_input {
Ok(parsed_input) => {
let run_start = Instant::now();
let result = (self.solver.run)(parsed_input);
let run_end = Instant::now();
println!("{}", result);
println!("\tparser: {:?}", parse_end - parse_start);
println!("\tsolver: {:?}", run_end - run_start);
}
Err(e) => eprintln!("Parser failed: {}", e),
}
Ok(())
}
fn day(&self) -> u8 {
self.day
}
}
pub struct Solver<F, I, O: std::fmt::Display>
where
F: Fn(I) -> O,
{
pub marker: PhantomData<I>,
pub name: &'static str,
pub run: F,
}