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}