1use std::str::FromStr;
2
3pub mod bits;
4pub mod intcode;
5pub mod linear;
6pub mod nom;
7pub mod scoring;
8pub mod spatial;
9
10pub trait Solution: FromStr {
14 type Output: std::fmt::Display + Default;
16
17 fn part1(&mut self) -> SolutionResult<Self::Output> {
19 todo!()
20 }
21
22 fn part2(&mut self) -> SolutionResult<Self::Output> {
24 todo!()
25 }
26
27 fn part3(&mut self) -> SolutionResult<Self::Output> {
29 Ok(Self::Output::default())
30 }
31
32 fn solve(&mut self, which: Part) -> SolutionResult<String> {
33 Ok(match which {
34 Part::One => self.part1()?.to_string(),
35 Part::Two => self.part2()?.to_string(),
36 Part::Three => self.part3()?.to_string(),
37 })
38 }
39}
40
41pub trait ArgSolution<A>: FromStr {
43 type Output: std::fmt::Display + Default;
45
46 fn part1(&mut self, _args: A) -> SolutionResult<Self::Output> {
48 todo!()
49 }
50
51 fn part2(&mut self, _args: A) -> SolutionResult<Self::Output> {
53 todo!()
54 }
55
56 fn part3(&mut self, _args: A) -> SolutionResult<Self::Output> {
58 Ok(Self::Output::default())
59 }
60
61 fn solve(&mut self, which: Part, args: A) -> SolutionResult<String> {
62 Ok(match which {
63 Part::One => ArgSolution::part1(self, args)?.to_string(),
64 Part::Two => ArgSolution::part2(self, args)?.to_string(),
65 Part::Three => ArgSolution::part3(self, args)?.to_string(),
66 })
67 }
68}
69
70#[derive(Debug, Clone, Copy)]
72pub enum Part {
73 One,
75 Two,
77 Three,
79}
80
81#[cfg(feature = "miette")]
82pub type SolutionResult<T> = miette::Result<T>;
83#[cfg(not(feature = "miette"))]
84pub type SolutionResult<T> = Result<T, Box<dyn std::error::Error>>;
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 struct Day;
91
92 impl Solution for Day {
93 type Output = String;
94
95 fn part1(&mut self) -> miette::Result<Self::Output> {
96 Ok("Hello, Rudolph!".into())
97 }
98
99 fn part2(&mut self) -> miette::Result<Self::Output> {
100 Ok("Hello, Santa!".into())
101 }
102 }
103
104 impl FromStr for Day {
105 type Err = miette::Error;
106
107 fn from_str(_input: &str) -> miette::Result<Self> {
108 Ok(Self)
109 }
110 }
111
112 #[test]
113 fn test_part_1() -> miette::Result<()> {
114 let mut day = Day::from_str("")?;
115
116 let solution = day.solve(Part::One)?;
117 assert_eq!("Hello, Rudolph!".to_string(), solution);
118 Ok(())
119 }
120
121 #[test]
122 fn test_part_2() -> miette::Result<()> {
123 let mut day: Day = "".parse()?;
124
125 let solution = day.solve(Part::Two)?;
126 assert_eq!("Hello, Santa!".to_string(), solution);
127 Ok(())
128 }
129
130 #[test]
131 fn test_part_3() {
132 let mut day = Day;
133
134 let solution = day.solve(Part::Three).unwrap();
135 assert_eq!("".to_string(), solution);
136 }
137}