1use crate::Aoc;
6use std::marker::PhantomData;
7use std::time::Instant;
8
9use anyhow::Result;
10
11use crate::input::get_input;
12use crate::parser::Parsing;
13
14pub trait Solvable {
18 fn run(&self, aoc: &Aoc) -> Result<()>;
19 fn day(&self) -> u8;
20}
21
22pub struct Solution<P, S, I, O: std::fmt::Display>
24where
25 P: Parsing<I>,
26 S: Fn(I) -> O,
27{
28 pub day: u8,
30 pub parser: P,
32 pub solver: Solver<S, I, O>,
34}
35
36impl<P, S, I, O: std::fmt::Display> Solvable for Solution<P, S, I, O>
37where
38 P: Parsing<I>,
39 S: Fn(I) -> O,
40{
41 fn run(&self, aoc: &Aoc) -> Result<()> {
42 let input = get_input(aoc, self.day)?;
43
44 print!(
45 "Day {} - {} with {}: ",
46 self.day,
47 self.solver.name,
48 self.parser.name()
49 );
50
51 let parse_start = Instant::now();
52 let parsed_input = self.parser.run(&input);
53 let parse_end = Instant::now();
54
55 match parsed_input {
56 Ok(parsed_input) => {
57 let run_start = Instant::now();
58 let result = (self.solver.run)(parsed_input);
59 let run_end = Instant::now();
60
61 println!("{}", result);
62 println!("\tparser: {:?}", parse_end - parse_start);
63 println!("\tsolver: {:?}", run_end - run_start);
64 }
65 Err(e) => eprintln!("Parser failed: {}", e),
66 }
67
68 Ok(())
69 }
70
71 fn day(&self) -> u8 {
72 self.day
73 }
74}
75
76pub struct Solver<F, I, O: std::fmt::Display>
81where
82 F: Fn(I) -> O,
83{
84 pub marker: PhantomData<I>,
85 pub name: &'static str,
86 pub run: F,
87}