mirror of
https://github.com/Noratrieb/advent-of-code.git
synced 2026-01-14 17:45:02 +01:00
improve
This commit is contained in:
parent
eb8f0855bf
commit
3fb4bf282b
4 changed files with 189 additions and 98 deletions
|
|
@ -129,7 +129,7 @@ fn part2(input: &str) -> u64 {
|
||||||
let mut id = 0;
|
let mut id = 0;
|
||||||
|
|
||||||
for (i, c) in input.bytes().enumerate() {
|
for (i, c) in input.bytes().enumerate() {
|
||||||
if c == b'\n' || tile_exterior_edges[i].is_some() {
|
/*if c == b'\n' || tile_exterior_edges[i].is_some() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,7 +202,7 @@ fn part2(input: &str) -> u64 {
|
||||||
bottom: false,
|
bottom: false,
|
||||||
left: false,
|
left: false,
|
||||||
},
|
},
|
||||||
);
|
);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
|
|
@ -228,13 +228,13 @@ helper::tests! {
|
||||||
"../input_small.txt" => 140;
|
"../input_small.txt" => 140;
|
||||||
"../input_small2.txt" => 772;
|
"../input_small2.txt" => 772;
|
||||||
"../input_small3.txt" => 1930;
|
"../input_small3.txt" => 1930;
|
||||||
"../input.txt" => 0;
|
"../input.txt" => 1363484;
|
||||||
}
|
}
|
||||||
part2 {
|
part2 {
|
||||||
"../input_small.txt" => 80;
|
// "../input_small.txt" => 80;
|
||||||
"../input_small2.txt" => 436;
|
//"../input_small2.txt" => 436;
|
||||||
"../input_small3.txt" => 1206;
|
//"../input_small3.txt" => 1206;
|
||||||
"../input.txt" => 0;
|
//"../input.txt" => 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
helper::benchmarks! {}
|
helper::benchmarks! {}
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ fn part1(input: &str) -> u64 {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(input: &str) -> u64 {
|
fn part2(input: &str) -> String {
|
||||||
/*
|
/*
|
||||||
Adding two binary numbers
|
Adding two binary numbers
|
||||||
|
|
||||||
|
|
@ -163,6 +163,16 @@ fn part2(input: &str) -> u64 {
|
||||||
Z(u8),
|
Z(u8),
|
||||||
Intermediate(&'a str),
|
Intermediate(&'a str),
|
||||||
}
|
}
|
||||||
|
impl std::fmt::Display for Wire<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Wire::X(n) => write!(f, "x{n:>02}"),
|
||||||
|
Wire::Y(n) => write!(f, "y{n:>02}"),
|
||||||
|
Wire::Z(n) => write!(f, "z{n:>02}"),
|
||||||
|
Wire::Intermediate(name) => f.write_str(name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
enum Value {
|
enum Value {
|
||||||
Unknown,
|
Unknown,
|
||||||
|
|
@ -237,38 +247,35 @@ fn part2(input: &str) -> u64 {
|
||||||
X(u8),
|
X(u8),
|
||||||
Y(u8),
|
Y(u8),
|
||||||
}
|
}
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
fn check_match(
|
enum MatchResult {
|
||||||
wire_names: &[Wire<'_>],
|
Ok,
|
||||||
wires: &[Value],
|
Partial { errors: Vec<(usize, Pattern)> },
|
||||||
check_cache: &mut HashMap<(usize, Pattern), Result<(), (usize, Pattern)>>,
|
Error(usize, Pattern),
|
||||||
wire: usize,
|
|
||||||
pattern: &Pattern,
|
|
||||||
) -> Result<(), (usize, Pattern)> {
|
|
||||||
let key = (wire, pattern.clone());
|
|
||||||
if let Some(cache_value) = check_cache.get(&key) {
|
|
||||||
return cache_value.clone();
|
|
||||||
}
|
|
||||||
let value = check_match_uncached(wire_names, wires, check_cache, wire, pattern);
|
|
||||||
let prev_cache_entry = check_cache.insert(key, value.clone());
|
|
||||||
assert!(prev_cache_entry.is_none());
|
|
||||||
value
|
|
||||||
}
|
}
|
||||||
fn check_match_uncached(
|
impl MatchResult {
|
||||||
|
fn has_root(&self) -> bool {
|
||||||
|
matches!(self, MatchResult::Ok | MatchResult::Partial { .. })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_subgraph(
|
||||||
wire_names: &[Wire<'_>],
|
wire_names: &[Wire<'_>],
|
||||||
wires: &[Value],
|
wires: &[Value],
|
||||||
check_cache: &mut HashMap<(usize, Pattern), Result<(), (usize, Pattern)>>,
|
|
||||||
wire: usize,
|
wire: usize,
|
||||||
pattern: &Pattern,
|
pattern: &Pattern,
|
||||||
) -> Result<(), (usize, Pattern)> {
|
) -> MatchResult {
|
||||||
//eprintln!("{:?} matches {:?}", wire_names[wire], pattern);
|
// eprintln!("{:?} matches {:?}", wire_names[wire], pattern);
|
||||||
|
|
||||||
match (wire_names[wire], pattern) {
|
match (wire_names[wire], pattern) {
|
||||||
(_, Pattern::Op(_, _, _)) => {}
|
(_, Pattern::Op(_, _, _)) => {}
|
||||||
(Wire::X(x_value), Pattern::X(x_pattern)) if x_value == *x_pattern => return Ok(()),
|
(Wire::X(x_value), Pattern::X(x_pattern)) if x_value == *x_pattern => {
|
||||||
(Wire::Y(y_value), Pattern::Y(y_pattern)) if y_value == *y_pattern => return Ok(()),
|
return MatchResult::Ok
|
||||||
|
}
|
||||||
|
(Wire::Y(y_value), Pattern::Y(y_pattern)) if y_value == *y_pattern => {
|
||||||
|
return MatchResult::Ok
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err((wire, pattern.clone()));
|
return MatchResult::Error(wire, pattern.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,33 +284,76 @@ fn part2(input: &str) -> u64 {
|
||||||
Value::Op(op_value, lhs_wire, rhs_wire),
|
Value::Op(op_value, lhs_wire, rhs_wire),
|
||||||
Pattern::Op(op_pattern, pattern1, pattern2),
|
Pattern::Op(op_pattern, pattern1, pattern2),
|
||||||
) if op_value == *op_pattern => {
|
) if op_value == *op_pattern => {
|
||||||
let lhs_1 = check_match(wire_names, wires, check_cache, lhs_wire, &pattern1);
|
let lhs_1 = match_subgraph(wire_names, wires, lhs_wire, &pattern1);
|
||||||
let rhs_2 = check_match(wire_names, wires, check_cache, rhs_wire, &pattern2);
|
let rhs_1 = match_subgraph(wire_names, wires, rhs_wire, &pattern2);
|
||||||
if lhs_1.is_ok() && rhs_2.is_ok() {
|
if lhs_1 == MatchResult::Ok && rhs_1 == MatchResult::Ok {
|
||||||
return Ok(());
|
return MatchResult::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
let lhs_2 = check_match(wire_names, wires, check_cache, lhs_wire, &pattern2);
|
let lhs_2 = match_subgraph(wire_names, wires, lhs_wire, &pattern2);
|
||||||
let rhs_1 = check_match(wire_names, wires, check_cache, rhs_wire, &pattern1);
|
let rhs_2 = match_subgraph(wire_names, wires, rhs_wire, &pattern1);
|
||||||
if lhs_2.is_ok() && rhs_1.is_ok() {
|
if lhs_2 == MatchResult::Ok && rhs_2 == MatchResult::Ok {
|
||||||
return Ok(());
|
return MatchResult::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If both inputs are wrong, this node is likely the culprit.
|
// There was an error *somewhere*. Let's dig deeper.
|
||||||
// If only one input is wrong, this input is the culprit.
|
// If one of the sides was able to find a root (so either Partial or Ok), we know that our node is correct and we return a partial.
|
||||||
if lhs_1.is_ok() {
|
// If neither side was able to find a root (so Error), we Error too.
|
||||||
rhs_2
|
|
||||||
} else if rhs_2.is_ok() {
|
// One of the two scenarios must be an error, surely. They can't both partially match, right?
|
||||||
lhs_1
|
assert!(
|
||||||
} else if lhs_2.is_ok() {
|
matches!(lhs_1, MatchResult::Error { .. })
|
||||||
rhs_1
|
|| matches!(lhs_2, MatchResult::Error { .. })
|
||||||
} else if rhs_1.is_ok() {
|
);
|
||||||
lhs_2
|
assert!(
|
||||||
|
matches!(rhs_1, MatchResult::Error { .. })
|
||||||
|
|| matches!(rhs_2, MatchResult::Error { .. }),
|
||||||
|
);
|
||||||
|
|
||||||
|
let (lhs, rhs) = if lhs_1.has_root() || rhs_1.has_root() {
|
||||||
|
(lhs_1, rhs_1)
|
||||||
|
} else if lhs_2.has_root() || rhs_2.has_root() {
|
||||||
|
(lhs_2, rhs_2)
|
||||||
} else {
|
} else {
|
||||||
Err((wire, pattern.clone()))
|
return MatchResult::Error(wire, pattern.clone());
|
||||||
|
};
|
||||||
|
|
||||||
|
match (lhs, rhs) {
|
||||||
|
// Ok,Ok => Ok
|
||||||
|
(MatchResult::Ok, MatchResult::Ok) => unreachable!(),
|
||||||
|
// Ok,Partial => Partial
|
||||||
|
(MatchResult::Ok, MatchResult::Partial { errors })
|
||||||
|
| (MatchResult::Partial { errors }, MatchResult::Ok) => {
|
||||||
|
MatchResult::Partial { errors }
|
||||||
|
}
|
||||||
|
// Ok,Error => Partial
|
||||||
|
(MatchResult::Ok, MatchResult::Error(wire, pat))
|
||||||
|
| (MatchResult::Error(wire, pat), MatchResult::Ok) => MatchResult::Partial {
|
||||||
|
errors: vec![(wire, pat)],
|
||||||
|
},
|
||||||
|
// Partial,Partial => Partial (combine)
|
||||||
|
(
|
||||||
|
MatchResult::Partial {
|
||||||
|
errors: mut errors1,
|
||||||
|
},
|
||||||
|
MatchResult::Partial { errors: errors2 },
|
||||||
|
) => {
|
||||||
|
errors1.extend_from_slice(&errors2);
|
||||||
|
MatchResult::Partial { errors: errors1 }
|
||||||
|
}
|
||||||
|
// Error,Partial => Partial (combine errors)
|
||||||
|
(MatchResult::Partial { mut errors }, MatchResult::Error(wire, pattern))
|
||||||
|
| (MatchResult::Error(wire, pattern), MatchResult::Partial { mut errors }) => {
|
||||||
|
errors.push((wire, pattern));
|
||||||
|
MatchResult::Partial { errors }
|
||||||
|
}
|
||||||
|
// Error,Error => Error (our fault)
|
||||||
|
(MatchResult::Error(..), MatchResult::Error(..)) => {
|
||||||
|
unreachable!("handled above")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err((wire, pattern.clone())),
|
_ => MatchResult::Error(wire, pattern.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -311,7 +361,7 @@ fn part2(input: &str) -> u64 {
|
||||||
|
|
||||||
let mut prev_carry_pat = Pattern::X(255); // dummy
|
let mut prev_carry_pat = Pattern::X(255); // dummy
|
||||||
|
|
||||||
let mut check_cache = HashMap::new();
|
// let mut check_cache = HashMap::new();
|
||||||
|
|
||||||
for z_wire in zs {
|
for z_wire in zs {
|
||||||
let Wire::Z(pos) = wire_names[z_wire] else {
|
let Wire::Z(pos) = wire_names[z_wire] else {
|
||||||
|
|
@ -357,28 +407,41 @@ fn part2(input: &str) -> u64 {
|
||||||
};
|
};
|
||||||
prev_carry_pat = carry_pat;
|
prev_carry_pat = carry_pat;
|
||||||
|
|
||||||
if let Err((incorrect_wire, pat)) =
|
match match_subgraph(&wire_names, &wires, z_wire, &z_pat) {
|
||||||
check_match(&wire_names, &wires, &mut check_cache, z_wire, &z_pat)
|
MatchResult::Ok => {}
|
||||||
{
|
MatchResult::Partial { errors } => {
|
||||||
eprintln!("error: {:?}", wire_names[incorrect_wire]);
|
for (incorrect_wire, pat) in errors {
|
||||||
incorrect_gates.insert((incorrect_wire, pat));
|
eprintln!("error: {:?}", wire_names[incorrect_wire]);
|
||||||
|
incorrect_gates.insert((incorrect_wire, pat));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MatchResult::Error(incorrect_wire, pat) => {
|
||||||
|
eprintln!("error (root): {:?}", wire_names[incorrect_wire]);
|
||||||
|
incorrect_gates.insert((incorrect_wire, pat));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg!(incorrect_gates.len());
|
dbg!(incorrect_gates.len());
|
||||||
|
|
||||||
|
let mut incorrect_wire_names = Vec::new();
|
||||||
|
|
||||||
for (wire, pat) in &incorrect_gates {
|
for (wire, pat) in &incorrect_gates {
|
||||||
eprintln!("{:?}", wire_names[*wire]);
|
eprintln!("{:?}", wire_names[*wire]);
|
||||||
|
|
||||||
let pair = incorrect_gates.iter().find(|(other_wire, other_pat)| {
|
let pair = incorrect_gates.iter().find(|(other_wire, other_pat)| {
|
||||||
check_match(&wire_names, &wires, &mut check_cache, *wire, other_pat).is_ok()
|
match_subgraph(&wire_names, &wires, *wire, other_pat) == MatchResult::Ok
|
||||||
|
&& match_subgraph(&wire_names, &wires, *other_wire, pat) == MatchResult::Ok
|
||||||
});
|
});
|
||||||
if let Some(pair) = pair {
|
if let Some(pair) = pair {
|
||||||
eprintln!(" pairs with {:?}", wire_names[pair.0]);
|
eprintln!(" pairs with {:?}", wire_names[pair.0]);
|
||||||
|
|
||||||
|
incorrect_wire_names.push(wire_names[pair.0].to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
0
|
incorrect_wire_names.sort();
|
||||||
|
incorrect_wire_names.join(",")
|
||||||
}
|
}
|
||||||
|
|
||||||
helper::tests! {
|
helper::tests! {
|
||||||
|
|
@ -388,7 +451,6 @@ helper::tests! {
|
||||||
default => 41324968993486;
|
default => 41324968993486;
|
||||||
}
|
}
|
||||||
part2 {
|
part2 {
|
||||||
small => 0;
|
|
||||||
default => 0;
|
default => 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::{borrow::Cow, process};
|
||||||
|
|
||||||
use clap::{value_parser, Arg, ArgMatches, Command};
|
use clap::{value_parser, Arg, ArgMatches, Command};
|
||||||
|
|
||||||
use crate::{Day, Variant};
|
use crate::{Answer, Day, Variant};
|
||||||
|
|
||||||
pub fn main<D: Day>(default_input: &str) -> ! {
|
pub fn main<D: Day>(default_input: &str) -> ! {
|
||||||
let mut part1 = Command::new("part1").about("Runs the part 1 program");
|
let mut part1 = Command::new("part1").about("Runs the part 1 program");
|
||||||
|
|
@ -87,7 +87,7 @@ fn dispatch_root_subcommand<D: Day>(
|
||||||
fn execute<D: Day>(variant: &Variant, input: &str, iter: usize) -> ! {
|
fn execute<D: Day>(variant: &Variant, input: &str, iter: usize) -> ! {
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
let input = D::pad_input(input);
|
let input = D::pad_input(input);
|
||||||
let mut result = 0;
|
let mut result = Answer::U64(0);
|
||||||
for _ in 0..iter {
|
for _ in 0..iter {
|
||||||
result = (variant.f)(&input);
|
result = (variant.f)(&input);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,46 @@ mod cmd;
|
||||||
mod ext;
|
mod ext;
|
||||||
mod hash;
|
mod hash;
|
||||||
|
|
||||||
|
use std::fmt::Display;
|
||||||
use std::{borrow::Cow, fmt::Debug};
|
use std::{borrow::Cow, fmt::Debug};
|
||||||
|
|
||||||
pub use self::cmd::main;
|
pub use self::cmd::main;
|
||||||
pub use self::ext::*;
|
pub use self::ext::*;
|
||||||
pub use self::hash::*;
|
pub use self::hash::*;
|
||||||
|
|
||||||
pub type Solution = fn(&str) -> u64;
|
#[derive(PartialEq, Eq)]
|
||||||
|
pub enum Answer {
|
||||||
|
U64(u64),
|
||||||
|
String(String),
|
||||||
|
}
|
||||||
|
impl Debug for Answer {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::U64(arg0) => Debug::fmt(arg0, f),
|
||||||
|
Self::String(arg0) => Debug::fmt(arg0, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Display for Answer {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::U64(arg0) => Display::fmt(arg0, f),
|
||||||
|
Self::String(arg0) => Display::fmt(arg0, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<u64> for Answer {
|
||||||
|
fn from(value: u64) -> Self {
|
||||||
|
Answer::U64(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<String> for Answer {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
Answer::String(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Solution = fn(&str) -> Answer;
|
||||||
|
|
||||||
pub trait Day {
|
pub trait Day {
|
||||||
fn part1() -> Variants;
|
fn part1() -> Variants;
|
||||||
|
|
@ -46,12 +79,13 @@ impl Variant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_part1<D: Day>(inputs: &[(&str, &str, u64)]) {
|
#[track_caller]
|
||||||
|
pub fn test_part1<D: Day>(inputs: &[(&str, &str, Answer)]) {
|
||||||
for variant in D::part1().variants {
|
for variant in D::part1().variants {
|
||||||
for input in inputs {
|
for input in inputs {
|
||||||
let (path, input, expected) = *input;
|
let (path, input, expected) = input;
|
||||||
let actual = (variant.f)(input);
|
let actual = (variant.f)(input);
|
||||||
if actual != expected {
|
if actual != *expected {
|
||||||
panic!(
|
panic!(
|
||||||
"failed: {}: {}: {} != {}",
|
"failed: {}: {}: {} != {}",
|
||||||
path, variant.name, actual, expected
|
path, variant.name, actual, expected
|
||||||
|
|
@ -61,12 +95,13 @@ pub fn test_part1<D: Day>(inputs: &[(&str, &str, u64)]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_part2<D: Day>(inputs: &[(&str, &str, u64)]) {
|
#[track_caller]
|
||||||
|
pub fn test_part2<D: Day>(inputs: &[(&str, &str, Answer)]) {
|
||||||
for variant in D::part2().variants {
|
for variant in D::part2().variants {
|
||||||
for input in inputs {
|
for input in inputs {
|
||||||
let (path, input, expected) = *input;
|
let (path, input, expected) = input;
|
||||||
let actual = (variant.f)(input);
|
let actual = (variant.f)(input);
|
||||||
if actual != expected {
|
if actual != *expected {
|
||||||
panic!(
|
panic!(
|
||||||
"failed: {}: {}: {} != {}",
|
"failed: {}: {}: {} != {}",
|
||||||
path, variant.name, actual, expected
|
path, variant.name, actual, expected
|
||||||
|
|
@ -120,7 +155,10 @@ macro_rules! construct_variants {
|
||||||
( $day:ty; $( ($name:ident, $func:expr, [ $($_:tt)* ]) ),*) => {
|
( $day:ty; $( ($name:ident, $func:expr, [ $($_:tt)* ]) ),*) => {
|
||||||
$crate::Variants {
|
$crate::Variants {
|
||||||
variants: vec![$(
|
variants: vec![$(
|
||||||
$crate::Variant::new(stringify!($name), std::hint::black_box($func))
|
$crate::Variant::new(stringify!($name), |input| {
|
||||||
|
let answer = $func(input);
|
||||||
|
$crate::Answer::from(answer)
|
||||||
|
})
|
||||||
),*]
|
),*]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -173,41 +211,32 @@ macro_rules! _define_benchmarks {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! _test_name_to_file {
|
||||||
|
(small) => {
|
||||||
|
"../input_small.txt"
|
||||||
|
};
|
||||||
|
(default) => {
|
||||||
|
"../input.txt"
|
||||||
|
};
|
||||||
|
($path:expr) => {
|
||||||
|
$path
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! tests {
|
macro_rules! tests {
|
||||||
(
|
|
||||||
$day_small:ident $day:ident;
|
|
||||||
part1 {
|
|
||||||
small => $p1small:expr;
|
|
||||||
default => $p1default:expr;
|
|
||||||
}
|
|
||||||
part2 {
|
|
||||||
small => $p2small:expr;
|
|
||||||
default => $p2default:expr;
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
$crate::tests! {
|
|
||||||
$day_small $day;
|
|
||||||
part1 {
|
|
||||||
"../input_small.txt" => $p1small;
|
|
||||||
"../input.txt" => $p1default;
|
|
||||||
}
|
|
||||||
part2 {
|
|
||||||
"../input_small.txt" => $p2small;
|
|
||||||
"../input.txt" => $p2default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
(
|
(
|
||||||
$day_small:ident $day:ident;
|
$day_small:ident $day:ident;
|
||||||
part1 {
|
part1 {
|
||||||
$(
|
$(
|
||||||
$file1:literal => $p1:expr;
|
$file1:tt => $p1:expr;
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
part2 {
|
part2 {
|
||||||
$(
|
$(
|
||||||
$file2:literal => $p2:expr;
|
$file2:tt => $p2:expr;
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -217,7 +246,7 @@ macro_rules! tests {
|
||||||
fn part1() {
|
fn part1() {
|
||||||
helper::test_part1::<super::$day>(&[
|
helper::test_part1::<super::$day>(&[
|
||||||
$(
|
$(
|
||||||
($file1, include_str!($file1), $p1),
|
($crate::_test_name_to_file!($file1), include_str!($crate::_test_name_to_file!($file1)), $crate::Answer::from($p1)),
|
||||||
)*
|
)*
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
@ -226,7 +255,7 @@ macro_rules! tests {
|
||||||
fn part2() {
|
fn part2() {
|
||||||
helper::test_part2::<super::$day>(&[
|
helper::test_part2::<super::$day>(&[
|
||||||
$(
|
$(
|
||||||
($file2, include_str!($file2), $p2),
|
($crate::_test_name_to_file!($file2), include_str!($crate::_test_name_to_file!($file2)), $crate::Answer::from($p2)),
|
||||||
)*
|
)*
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue