#[bin_setup]Expand description
This macro can be used to generate my standard approach to Advent of Code binaries.
It can only be attached to fn main().
Required arguments:
puzzles_count, number of puzzles in the binaryresources_directory, path to inputs and answers files, relative tosrcinput_extension, input files extensionanswers_file, file containing the puzzle answers for checking execution
A simple pretty_solution_2 macro is provided to:
- embed input strings
- execute solutions
- measure execution time
- verify output against provided answers
The generated main function provides args handling to execute only specific days, e.g. $ executable 1 3 5
Example usage:
use aoc_core_macros::bin_setup;
#[bin_setup(5, "../resources", ".in", "Answers.out")]
fn main() {
pretty_solution_2!(5, "PuzzleX", solution1, solution2);
}
fn solution1(input: &str) -> u8 {
input.lines().map(|n| n.parse::<u8>().unwrap()).sum()
}
fn solution2(input: &str) -> u8 {
input.lines().map(|n| n.parse::<u8>().unwrap()).product()
}
// ../resources/PuzzleX.in
// 2
// 3
// ../resources/Answers.out
// PuzzleX 5 6Generated code looks like this:
#[allow(clippy::items_after_statements)]
fn main() {
let puzzle_answers: rustc_hash::FxHashMap<&'static str, [&'static str; 2]> =
include_str!(concat!("../resources", "/", "Answers.out"))
.lines()
.map(|line| {
let parts: Vec<_> = line.split_ascii_whitespace().collect();
(parts[0], [parts[1], parts[2]])
})
.collect();
let selected_puzzles: [bool; 5] = {
let args: Vec<_> = std::env::args().collect();
if args.len() == 1 {
[true; 5]
} else {
std::array::from_fn(|day| args.contains(&(day + 1).to_string()))
}
};
#[inline]
fn pretty_solution<R>(
puzzle: &str,
part: usize,
solution: fn(&str) -> R,
input: &str,
answer: &str,
) where
R: std::fmt::Display + PartialEq,
{
let now = std::time::Instant::now();
let solution = solution(input);
let microseconds = now.elapsed().as_micros();
assert!(
solution.to_string() == answer,
"Wrong solution for {puzzle} part {part}: expected {answer}, but got {solution}"
);
println!("{part} -> {answer} ({microseconds}μs)");
}
macro_rules! pretty_solution_2 {
($day:literal, $puzzle: literal, $solution1:ident $(,$solution2:ident)?) => {
if selected_puzzles[$day - 1] {
println!("Day {}: {}", $day, $puzzle);
const INPUT: &str =
include_str!(concat!("../resources", "/", $puzzle, ".in"));
let answers = puzzle_answers.get($puzzle).expect("Puzzle answer not found");
pretty_solution($puzzle, 1, $solution1, INPUT, answers[0]);
$(pretty_solution($puzzle, 2, $solution2, INPUT, answers[1]);)?
println!();
}
};
}
pretty_solution_2!(5, "PuzzleX", solution1, solution2);
}