1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
//! # `impl Solution<'_, Day25, Part2> for AdventOfCode2021<Day25>`
//!
//! ## What is this?
//!
//! This is [`advent_of_code_traits`](https://github.com/drmason13/advent_of_code_traits), a set of traits to implement solutions to Advent of Code in Rust.
//!
//! It takes a trait-based approach using const-generics and autoderef specialization.
//!
//! It's basically an excuse to play with rust's type system.
//!
//! ## Usage
//!
//! Please see also the [examples](https://github.com/drmason13/advent_of_code_traits/tree/main/examples).
//!
//! Implement traits with your solutions to each day of Advent of Code.
//!
//! ### Import the machinery:
//!
//! ```
//! use advent_of_code_traits::{days::*, MissingPartTwo, Part1, Part2, ParseInput, run, Solution, SolutionRunner};
//! ```
//!
//! ### Implement [`Solution`] for your struct.
//!
//! ```
//! # use advent_of_code_traits::{days::*, MissingPartTwo, Part1, Part2, ParseInput, run, Solution, SolutionRunner};
//! pub struct AdventOfCode2021<const DAY: u32>;
//!
//! impl Solution<'_, Day25, Part1> for AdventOfCode2021<Day25> {
//!     type Input = Vec<u32>;
//!     type Output = u32;
//!
//!     fn solve(&self, input: &Self::Input) -> Self::Output {
//!         // your solution to Part1 here...
//! #       1
//!     }
//! }
//!
//! # impl ParseInput<'_, Day25, Part1> for AdventOfCode2021<Day25> {
//! #     type Parsed = Vec<u32>; // <-- the input to both PartOne and PartTwo for Solution<Day1>
//! #
//! #     fn parse_input(&self, input: &str) -> Self::Parsed {
//! #         input
//! #             .lines()
//! #             .map(|s| s.parse().expect("invalid integer"))
//! #             .collect()
//! #     }
//! # }
//! # impl MissingPartTwo<Day25> for AdventOfCode2021<Day25> {}
//! ```
//!
//! That's how we solve the solution given a nicely typed `Vec<u32>`, but Advent of Code gives us plaintext input.
//!
//! So first we need to parse the input...
//!
//! ### Implement [`ParseInput`] for your struct
//!
//! ```
//! # use advent_of_code_traits::{days::*, MissingPartTwo, Part1, Part2, ParseInput, run, Solution, SolutionRunner};
//! # pub struct AdventOfCode2021<const DAY: u32>;
//! #
//! # impl Solution<'_, Day25, Part1> for AdventOfCode2021<Day25> {
//! #     type Input = Vec<u32>;
//! #     type Output = u32;
//! #
//! #     fn solve(&self, input: &Vec<u32>) -> u32 {
//! #         // your solution to Part1 here...
//! #         1
//! #     }
//! # }
//! // ..continued from above
//!
//! impl ParseInput<'_, Day25, Part1> for AdventOfCode2021<Day25> {
//!     type Parsed = Vec<u32>; // <-- the input type fed to Solution::solve
//!
//!     fn parse_input(&self, input: &'_ str) -> Self::Parsed {
//!         input
//!             .lines()
//!             .map(|s| s.parse().expect("invalid integer"))
//!             .collect()
//!     }
//! }
//! # let input = "1\n2\n3";
//! # impl MissingPartTwo<Day25> for AdventOfCode2021<Day25> {}
//! # let prb = AdventOfCode2021::<Day25>;
//! # let parsed = &prb.parse_input(&input);
//! # let ans = prb.solve(&parsed);
//! # assert_eq!(1, ans);
//! ```
//!
//! ### Mark Part2 as missing
//!
//! To run only Part1 of a day of Advent of Code, you currently need to impl `MissingPartTwo` to help disambiguate the specialization:
//! ```no_run
//! impl MissingPartTwo<Day25> for AdventOfCode2021<Day25> {}
//! ```
//!
//! If you don't do this (and haven't implemented Solution for Part2) you'll see an error like:
//! ```text
//! the method `run` exists for reference `&&&AdventOfCode2021<25_u32>`, but its trait bounds were not satisfied
//! the following trait bounds were not satisfied:
//! `AdventOfCode2021<25_u32>: MissingPartTwo<25_u32>`
//! which is required by `AdventOfCode2021<25_u32>: SolutionRunner<25_u32, 1_u16>`rustcE0599
//! ```
//!
//! Please refer to the [examples](https://github.com/drmason13/advent_of_code_traits/tree/main/examples) for more demonstrations.
//!
//! ### Run from `main.rs`
//!
//! Here comes the part where we actually run our solution!
//! ```
//! # use advent_of_code_traits::{days::*, MissingPartTwo, Part1, Part2, ParseInput, run, Solution, SolutionRunner};
//! # pub struct AdventOfCode2021<const DAY: u32>;
//! #
//! # impl Solution<'_, Day25, Part1> for AdventOfCode2021<Day25> {
//! #     type Input = Vec<u32>;
//! #     type Output = u32;
//! #
//! #     fn solve(&self, input: &Vec<u32>) -> u32 {
//! #         // your solution to Part1 here...
//! #         1
//! #     }
//! # }
//! # impl ParseInput<'_, Day25, Part1> for AdventOfCode2021<Day25> {
//! #     type Parsed = Vec<u32>; // <-- the input to both PartOne and PartTwo for Solution<Day1>
//! #
//! #     fn parse_input(&self, input: &str) -> Self::Parsed {
//! #         input
//! #             .lines()
//! #             .map(|s| s.parse().expect("invalid integer"))
//! #             .collect()
//! #     }
//! # }
//! # impl MissingPartTwo<Day25> for AdventOfCode2021<Day25> {}
//! # // for test purposes, circumvent the example code
//! # if false {
//! let input = std::fs::read_to_string("./input/2021/day25.txt").expect("failed to read input");
//! # }
//! # let input = "1\n2\n3";
//! run!(AdventOfCode2021::<Day25>, &input);
//! ```
//! This reads input from a file and passes it to your struct to parse and then solve.
//! It will print the output of your solution (which must impl Debug).
//!
//! [`run`] is currently a humble `macro_rules!` declarative macro and is *very* simple.
//! It's main purpose is to veil the use of autoderef [`specialization`].
use std::fmt::Debug;

pub mod days;

#[allow(non_upper_case_globals)]
pub const Part1: u8 = 1;
#[allow(non_upper_case_globals)]
pub const Part2: u8 = 2;

/// Implement this trait with your solution to the Advent of Code problem for a particular day and part.
///
/// Remember: Day, then Part.
///
/// The compiler will complain about u32 (days) vs u8 (parts) if you mix this up.
pub trait Solution<'a, const DAY: u32, const PART: u8> {
    type Input;
    type Output: Debug;

    fn solve(&'a self, input: &Self::Input) -> Self::Output;
}

/// Implement this trait to parse the raw input into a more useful type for your [`Solution`] to use as input.
///
/// See [`Solution::Input`]
pub trait ParseInput<'a, const DAY: u32, const PART: u8> {
    type Parsed;

    fn parse_input(&'a self, input: &'a str) -> Self::Parsed;
}

/// Import this trait to run your advent of code solutions once they implement [`Solution`].
///
/// This trait doesn't need to be implemented outside of this crate.
///
/// Blanket implementations are provided that specialize if your solutions share a parsed input type or if [`MissingPartTwo`] is implemented.
pub trait SolutionRunner<'a, const DAY: u32, const IMPL: u16> {
    fn run(&'a self, input: &'a str);
}

/// The [`run`] macro expands
/// ```ignore
/// run!(AdventOfCode2021::<Day25>, &input);
/// ```
/// to
/// ```ignore
/// {
///     let problem = AdventOfCode2021::<Day25>;
///     (&&&problem).run(&input)
/// }
/// ```
/// and that's it!
///
/// What's with all the `&`s? It's autoderef specialization, see [`specialization`].
#[macro_export]
macro_rules! run {
    ($day: expr, $input: expr) => {{
        let problem = $day;
        (&&&problem).run($input)
    }};
}

/// [`MissingPartTwo`] is a marker trait to tell the compiler that your struct doesn't impl Solution for Part2.
///
/// Implementing this is required in order to run only Part1 using [`SolutionRunner::run`] without specifying which SolutionRunner impl to use manually.
///
/// Why? It's to guide the specialization by ensuring that each impl is unique. See [`specialization`] for more details.
/// ```
/// # use advent_of_code_traits::{days::Day1, MissingPartTwo, ParseInput, Part1, Solution, SolutionRunner };
/// struct AdventOfCode2021<const DAY: u32>;
///
/// impl<'a> Solution<'a, Day1, Part1> for AdventOfCode2021<Day1> {
///     // your solution to part 1
/// #     type Input = u32; type Output = u32;
/// #     fn solve(&'a self, _input: &Self::Input) -> Self::Output { 1 }
/// }
/// # impl<'a> ParseInput<'a, Day1, Part1> for AdventOfCode2021::<Day1> {
/// #     type Parsed = u32;
/// #     fn parse_input(&'a self, input: &'a str) -> Self::Parsed { 1 }
/// # }
///
/// // add this to be able to .run() AdventOfCode2021::<Day25> without an implemention for Part2
/// impl MissingPartTwo<Day1> for AdventOfCode2021<Day1> {}
///
/// # let input: &'static str = "fake input";
/// # let problem = AdventOfCode2021::<Day1>;
/// // ...
/// problem.run(&input);
/// ```
pub trait MissingPartTwo<const DAY: u32> {}

pub mod specialization;