diff --git a/2023/day1/input_small1.txt b/2023/day1/input_small1.txt new file mode 100644 index 0000000..7bbc69a --- /dev/null +++ b/2023/day1/input_small1.txt @@ -0,0 +1,4 @@ +1abc2 +pqr3stu8vwx +a1b2c3d4e5f +treb7uchet diff --git a/2023/day1/input_small2.txt b/2023/day1/input_small2.txt new file mode 100644 index 0000000..41aa89c --- /dev/null +++ b/2023/day1/input_small2.txt @@ -0,0 +1,7 @@ +two1nine +eightwothree +abcone2threexyz +xtwone3four +4nineeightseven2 +zoneight234 +7pqrstsixteen diff --git a/2023/day1/src/branchless.rs b/2023/day1/src/branchless.rs index b2df058..9480dfd 100644 --- a/2023/day1/src/branchless.rs +++ b/2023/day1/src/branchless.rs @@ -1,4 +1,4 @@ -pub unsafe fn part2(input: &str) { +pub unsafe fn part2(input: &str) -> u64 { let sum = input .lines() .map(|line| { @@ -73,5 +73,5 @@ pub unsafe fn part2(input: &str) { }) .sum::(); - println!("part2: {sum}"); + sum } diff --git a/2023/day1/src/main.rs b/2023/day1/src/main.rs index f0ba9a5..d9ff957 100644 --- a/2023/day1/src/main.rs +++ b/2023/day1/src/main.rs @@ -1,5 +1,7 @@ use std::mem::MaybeUninit; +use helper::{Day, Variant, Variants}; + mod branchless; mod naive; mod no_lines; @@ -30,10 +32,41 @@ fn main() { eprintln!("error: invalid mode, must be part1,naive,zero_alloc,branchless"); std::process::exit(1); } + }; +} + +struct Day1; + +impl Day for Day1 { + fn pad_input(input: &str) -> std::borrow::Cow { + let mut input = input.to_owned(); + input.reserve(10); // enough to read u64 + unsafe { + input + .as_mut_vec() + .spare_capacity_mut() + .fill(MaybeUninit::new(0)) + }; + std::borrow::Cow::Owned(input) + } + fn part1() -> Variants { + Variants::basic(part1) + } + + fn part2() -> Variants { + Variants { + variants: vec![ + Variant::new("naive", naive::part2), + Variant::new("zero_alloc", zero_alloc::part2), + Variant::new("branchless", |i| unsafe { branchless::part2(i) }), + Variant::new("no_lines", |i| unsafe { no_lines::part2(i) }), + Variant::new("vectorized", |i| unsafe { vectorized::part2(i) }), + ], + } } } -fn part1(input: &str) { +fn part1(input: &str) -> u64 { let sum = input .lines() .map(|line| { @@ -49,5 +82,17 @@ fn part1(input: &str) { }) .sum::(); - println!("part1: {sum}"); + sum +} + +helper::tests! { + day1 Day1; + part1 { + "../input_small1.txt" => 142; + "../input.txt" => 54632; + } + part2 { + "../input_small2.txt" => 281; + "../input.txt" => 54019; + } } diff --git a/2023/day1/src/naive.rs b/2023/day1/src/naive.rs index c835fa4..3b74b79 100644 --- a/2023/day1/src/naive.rs +++ b/2023/day1/src/naive.rs @@ -1,4 +1,4 @@ -pub fn part2(input: &str) { +pub fn part2(input: &str) -> u64 { let sum = input .lines() .map(|line| { @@ -24,5 +24,5 @@ pub fn part2(input: &str) { }) .sum::(); - println!("part2: {sum}"); -} + sum + } diff --git a/2023/day1/src/no_lines.rs b/2023/day1/src/no_lines.rs index 8a16c81..abdc37d 100644 --- a/2023/day1/src/no_lines.rs +++ b/2023/day1/src/no_lines.rs @@ -1,4 +1,4 @@ -pub unsafe fn part2(input: &str) { +pub unsafe fn part2(input: &str) -> u64 { let mut sum = 0; let bytes = input.as_bytes(); @@ -83,5 +83,5 @@ pub unsafe fn part2(input: &str) { line_idx += 1; } - println!("part2: {sum}"); + sum } diff --git a/2023/day1/src/vectorized.rs b/2023/day1/src/vectorized.rs index 80875ec..7ad9f51 100644 --- a/2023/day1/src/vectorized.rs +++ b/2023/day1/src/vectorized.rs @@ -1,4 +1,4 @@ -pub unsafe fn part2(input: &str) { +pub unsafe fn part2(input: &str) -> u64 { let mut sum = 0; let bytes = input.as_bytes(); @@ -152,5 +152,5 @@ pub unsafe fn part2(input: &str) { line_idx += 1; } - println!("part2: {sum}"); + sum } diff --git a/2023/day1/src/zero_alloc.rs b/2023/day1/src/zero_alloc.rs index 8a6b9c4..8f5b2d2 100644 --- a/2023/day1/src/zero_alloc.rs +++ b/2023/day1/src/zero_alloc.rs @@ -1,4 +1,4 @@ -pub fn part2(input: &str) { +pub fn part2(input: &str) -> u64 { let sum = input .lines() .map(|line| { @@ -39,5 +39,5 @@ pub fn part2(input: &str) { }) .sum::(); - println!("part2: {sum}"); -} + sum + } diff --git a/helper/src/lib.rs b/helper/src/lib.rs index 7b183b5..6e91601 100644 --- a/helper/src/lib.rs +++ b/helper/src/lib.rs @@ -33,6 +33,12 @@ impl Variants { } } +impl Variant { + pub fn new(name: &'static str, f: Solution) -> Self { + Self { name, f } + } +} + pub fn test_part1(inputs: &[(&str, u64)]) { for variant in D::part1().variants { for input in inputs { @@ -67,22 +73,49 @@ macro_rules! tests { 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; + part1 { + $( + $file1:literal => $p1:expr; + )* + } + part2 { + $( + $file2:literal => $p2:expr; + )* + } ) => { #[cfg(test)] mod $day_small { #[test] fn part1() { helper::test_part1::(&[ - (include_str!("../input_small.txt"), $p1small), - (include_str!("../input.txt"), $p1default), + $( + (include_str!($file1), $p1), + )* ]); } #[test] fn part2() { helper::test_part2::(&[ - (include_str!("../input_small.txt"), $p2small), - (include_str!("../input.txt"), $p2default), + $( + (include_str!($file2), $p2), + )* ]); } }