aoc/years.rs
1//! Implementation for [`all_puzzles!`](crate::all_puzzles!).
2//!
3//! Each of the year crates is re-exported below if the corresponding feature is enabled, or a
4//! placeholder crate with the [`utils::puzzles_noop!`] no-op `puzzles!` macro if it is not.
5//! The `puzzles!` macros are then chained together by [`all_puzzles!`](crate::all_puzzles!).
6//!
7//! This main advantage of this approach over passing `#[cfg(feature = ?)]` attributes to the
8//! callback is that it prevents disabled years from being expanded at all, which should speed up
9//! compilation.
10//!
11//! Running `cargo xtask update` will automatically update the list of re-exports.
12
13// xtask update re-exports
14#[cfg(not(feature = "year2015"))]
15pub mod year2015 {
16 pub use ::utils::puzzles_noop as puzzles;
17}
18#[cfg(not(feature = "year2016"))]
19pub mod year2016 {
20 pub use ::utils::puzzles_noop as puzzles;
21}
22#[cfg(not(feature = "year2017"))]
23pub mod year2017 {
24 pub use ::utils::puzzles_noop as puzzles;
25}
26#[cfg(not(feature = "year2018"))]
27pub mod year2018 {
28 pub use ::utils::puzzles_noop as puzzles;
29}
30#[cfg(not(feature = "year2019"))]
31pub mod year2019 {
32 pub use ::utils::puzzles_noop as puzzles;
33}
34#[cfg(not(feature = "year2024"))]
35pub mod year2024 {
36 pub use ::utils::puzzles_noop as puzzles;
37}
38#[cfg(not(feature = "year2025"))]
39pub mod year2025 {
40 pub use ::utils::puzzles_noop as puzzles;
41}
42#[cfg(feature = "year2015")]
43pub use ::year2015;
44#[cfg(feature = "year2016")]
45pub use ::year2016;
46#[cfg(feature = "year2017")]
47pub use ::year2017;
48#[cfg(feature = "year2018")]
49pub use ::year2018;
50#[cfg(feature = "year2019")]
51pub use ::year2019;
52#[cfg(feature = "year2024")]
53pub use ::year2024;
54#[cfg(feature = "year2025")]
55pub use ::year2025;
56
57/// Macro which invokes a callback macro with a list of all implemented puzzle solutions.
58///
59/// This macro chains `puzzles!` macros in the re-exported year modules. The callback macro will be
60/// called once with all the solutions, which makes it easy to generate match statements or arrays.
61///
62/// Running `cargo xtask update` will automatically update the chain of year macros.
63///
64/// # Examples
65///
66/// Simple `main` function to run all examples:
67///
68/// ```
69/// # use aoc::all_puzzles;
70/// # use utils::PuzzleExamples;
71/// # use utils::input::InputType;
72/// #
73/// macro_rules! callback {
74/// ($(
75/// $y:literal => $year:ident{$(
76/// $d:literal => $day:ident,
77/// )*}
78/// )*) => {$($(
79/// println!("{} {}", $y, $d);
80/// for (input_str, p1, p2) in aoc::$year::$day::EXAMPLES {
81/// let solution = aoc::$year::$day::new(input_str, InputType::Example).unwrap();
82/// println!(" parse({input_str}) = {solution:?}");
83/// if (p1.is_some()) { println!(" part1(...) = {}", solution.part1()); }
84/// if (p2.is_some()) { println!(" part2(...) = {}", solution.part2()); }
85/// }
86/// )*)*};
87/// }
88/// all_puzzles!(callback);
89/// ```
90///
91/// Generating a match statement:
92///
93/// ```
94/// # use aoc::all_puzzles;
95/// # use utils::date::Date;
96/// # use utils::{PuzzleExamples, PuzzleDate};
97/// #
98/// fn example_count(date: Date) -> Option<usize> {
99/// macro_rules! callback {
100/// ($(
101/// $y:literal => $year:ident{$(
102/// $d:literal => $day:ident,
103/// )*}
104/// )*) => {
105/// match date {
106/// $($(
107/// aoc::$year::$day::DATE => Some(aoc::$year::$day::EXAMPLES.len()),
108/// )*)*
109/// _ => None,
110/// }
111/// };
112/// }
113/// all_puzzles!{callback}
114/// }
115/// ```
116#[macro_export]
117macro_rules! all_puzzles {
118 ($callback:path $(,$arg:tt)*$(,)?) => {
119 $crate::utils::puzzles_noop!{
120 [
121 // xtask update all_puzzles
122 $crate::year2015::puzzles,
123 $crate::year2016::puzzles,
124 $crate::year2017::puzzles,
125 $crate::year2018::puzzles,
126 $crate::year2019::puzzles,
127 $crate::year2024::puzzles,
128 $crate::year2025::puzzles,
129
130 $callback
131 ]
132 $($arg)*
133 }
134 };
135}