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 = "year2024"))]
27pub mod year2024 {
28 pub use ::utils::puzzles_noop as puzzles;
29}
30#[cfg(feature = "year2015")]
31pub use ::year2015;
32#[cfg(feature = "year2016")]
33pub use ::year2016;
34#[cfg(feature = "year2017")]
35pub use ::year2017;
36#[cfg(feature = "year2024")]
37pub use ::year2024;
38
39/// Macro which invokes a callback macro with a list of all implemented puzzle solutions.
40///
41/// This macro chains `puzzles!` macros in the re-exported year modules. The callback macro will be
42/// called once with all the solutions, which makes it easy to generate match statements or arrays.
43///
44/// Running `cargo xtask update` will automatically update the chain of year macros.
45///
46/// # Examples
47///
48/// Simple `main` function to run all examples:
49///
50/// ```
51/// # use aoc::all_puzzles;
52/// # use utils::PuzzleExamples;
53/// # use utils::input::InputType;
54/// #
55/// macro_rules! callback {
56/// ($(
57/// $y:literal => $year:ident{$(
58/// $d:literal => $day:ident,
59/// )*}
60/// )*) => {$($(
61/// println!("{} {}", $y, $d);
62/// for (input_str, p1, p2) in aoc::$year::$day::EXAMPLES {
63/// let solution = aoc::$year::$day::new(input_str, InputType::Example).unwrap();
64/// println!(" parse({input_str}) = {solution:?}");
65/// if (p1.is_some()) { println!(" part1(...) = {}", solution.part1()); }
66/// if (p2.is_some()) { println!(" part2(...) = {}", solution.part2()); }
67/// }
68/// )*)*};
69/// }
70/// all_puzzles!(callback);
71/// ```
72///
73/// Generating a match statement:
74///
75/// ```
76/// # use aoc::all_puzzles;
77/// # use utils::date::{Day, Year};
78/// # use utils::{PuzzleExamples, Puzzle};
79/// #
80/// fn example_count(year: Year, day: Day) -> Option<usize> {
81/// macro_rules! callback {
82/// ($(
83/// $y:literal => $year:ident{$(
84/// $d:literal => $day:ident,
85/// )*}
86/// )*) => {
87/// match (year, day) {
88/// $($(
89/// (aoc::$year::$day::YEAR, aoc::$year::$day::DAY) => Some(aoc::$year::$day::EXAMPLES.len()),
90/// )*)*
91/// _ => None,
92/// }
93/// };
94/// }
95/// all_puzzles!{callback}
96/// }
97/// ```
98#[macro_export]
99macro_rules! all_puzzles {
100 ($callback:path $(,$arg:tt)*$(,)?) => {
101 $crate::utils::puzzles_noop!{
102 [
103 // xtask update all_puzzles
104 $crate::year2015::puzzles,
105 $crate::year2016::puzzles,
106 $crate::year2017::puzzles,
107 $crate::year2024::puzzles,
108
109 $callback
110 ]
111 $($arg)*
112 }
113 };
114}