diff --git a/src/bin/01.rs b/src/bin/01.rs index d2f7181..41e6610 100644 --- a/src/bin/01.rs +++ b/src/bin/01.rs @@ -1,16 +1,18 @@ +use aoc::*; + +const INPUT: &str = include_str!("../../input/01"); + fn main() { - let input = include_str!("../../input/01"); - println!("Part 1: {}", part1(input)); - println!("Part 2: {}", part2(input)); + println!("Part 1: {}", part1(INPUT)); + println!("Part 2: {}", part2(INPUT)); } #[test] fn example() { - let input = include_str!("../../input/01-test"); - assert_eq!(part1(input), 3); + assert_example!(part1, "01-test", 3); assert_eq!(part2("R1000"), 10); assert_eq!(part2("R950"), 10); - assert_eq!(part2(input), 6); + assert_example!(part2, "01-test", 6); } fn part1(input: &str) -> usize { diff --git a/src/bin/02.rs b/src/bin/02.rs index 57d4d50..53742cb 100644 --- a/src/bin/02.rs +++ b/src/bin/02.rs @@ -1,14 +1,16 @@ +use aoc::*; + +const INPUT: &str = include_str!("../../input/02"); + fn main() { - let input = include_str!("../../input/02"); - println!("Part 1: {}", part1(input)); - println!("Part 2: {}", part2(input)); + println!("Part 1: {}", part1(INPUT)); + println!("Part 2: {}", part2(INPUT)); } #[test] fn example() { - let input = include_str!("../../input/02-test"); - assert_eq!(part1(input), 1227775554); - assert_eq!(part2(input), 4174379265); + assert_example!(part1, "02-test", 1227775554); + assert_example!(part2, "02-test", 4174379265); } fn part1(input: &str) -> usize { diff --git a/src/bin/03.rs b/src/bin/03.rs index 95045a6..7ae9849 100644 --- a/src/bin/03.rs +++ b/src/bin/03.rs @@ -1,14 +1,16 @@ +use aoc::*; + +const INPUT: &str = include_str!("../../input/03"); + fn main() { - let input = include_str!("../../input/03"); - println!("Part 1: {}", part1(input)); - println!("Part 2: {}", part2(input)); + println!("Part 1: {}", part1(INPUT)); + println!("Part 2: {}", part2(INPUT)); } #[test] fn example() { - let input = include_str!("../../input/03-test"); - assert_eq!(part1(input), 357); - assert_eq!(part2(input), 3121910778619); + assert_example!(part1, "03-test", 357); + assert_example!(part2, "03-test", 3121910778619); } fn part1(input: &str) -> i64 { diff --git a/src/bin/04.rs b/src/bin/04.rs index b083385..3f0ce5a 100644 --- a/src/bin/04.rs +++ b/src/bin/04.rs @@ -2,17 +2,17 @@ use aoc::*; use glam::IVec2; use std::collections::HashSet; +const INPUT: &str = include_str!("../../input/04"); + fn main() { - let input = include_str!("../../input/04"); - println!("Part 1: {}", part1(input)); - println!("Part 2: {}", part2(input)); + println!("Part 1: {}", part1(INPUT)); + println!("Part 2: {}", part2(INPUT)); } #[test] fn example() { - let input = include_str!("../../input/04-test"); - assert_eq!(part1(input), 13); - assert_eq!(part2(input), 43); + assert_example!(part1, "04-test", 13); + assert_example!(part2, "04-test", 43); } fn part1(input: &str) -> usize { diff --git a/src/bin/05.rs b/src/bin/05.rs index 7eb7c02..f470db1 100644 --- a/src/bin/05.rs +++ b/src/bin/05.rs @@ -1,16 +1,17 @@ +use aoc::*; use itertools::Itertools; +const INPUT: &str = include_str!("../../input/05"); + fn main() { - let input = include_str!("../../input/05"); - println!("Part 1: {}", part1(input)); - println!("Part 2: {}", part2(input)); + println!("Part 1: {}", part1(INPUT)); + println!("Part 2: {}", part2(INPUT)); } #[test] fn example() { - let input = include_str!("../../input/05-test"); - assert_eq!(part1(input), 3); - assert_eq!(part2(input), 14); + assert_example!(part1, "05-test", 3); + assert_example!(part2, "05-test", 14); assert_eq!(part2("1-10\n5-6\n\n"), 10); assert_eq!(part2("1-10\n8-20\n\n"), 20); assert_eq!(part2("1-1\n2-2\n3-3\n\n"), 3); diff --git a/src/bin/06.rs b/src/bin/06.rs index 22c57bc..e133062 100644 --- a/src/bin/06.rs +++ b/src/bin/06.rs @@ -3,17 +3,17 @@ use aoc::*; use itertools::Itertools; use std::str::FromStr; +const INPUT: &str = include_str!("../../input/06"); + fn main() { - let input = include_str!("../../input/06"); - println!("Part 1: {}", part1(input)); - println!("Part 2: {}", part2(input)); + println!("Part 1: {}", part1(INPUT)); + println!("Part 2: {}", part2(INPUT)); } #[test] fn example() { - let input = include_str!("../../input/06-test"); - assert_eq!(part1(input), 4277556); - assert_eq!(part2(input), 3263827); + assert_example!(part1, "06-test", 4277556); + assert_example!(part2, "06-test", 3263827); } fn part1(input: &str) -> usize { diff --git a/src/bin/07.rs b/src/bin/07.rs index 5d50370..8deddc1 100644 --- a/src/bin/07.rs +++ b/src/bin/07.rs @@ -1,17 +1,18 @@ +use aoc::*; use cached::proc_macro::cached; use std::collections::HashSet; +const INPUT: &str = include_str!("../../input/07"); + fn main() { - let input = include_str!("../../input/07"); - println!("Part 1: {}", part1(input)); - println!("Part 2: {}", part2(input)); + println!("Part 1: {}", part1(INPUT)); + println!("Part 2: {}", part2(INPUT)); } #[test] fn example() { - let input = include_str!("../../input/07-test"); - assert_eq!(part1(input), 21); - assert_eq!(part2(input), 40); + assert_example!(part1, "07-test", 21); + assert_example!(part2, "07-test", 40); } fn part1(input: &str) -> usize { @@ -51,7 +52,10 @@ fn split_count(splitters: &HashSet, beams: HashSet) -> (usize, HashSet (count, result) } -#[cached(key = "(i32, usize)", convert = r#"{ (beam, depth) }"#)] +#[cached( + key = "(i32, usize)", + convert = r#"{ (beam, depth) }"# +)] fn timelines(beam: i32, depth: usize, splitters: &[HashSet]) -> usize { if depth >= splitters.len() { return 1; diff --git a/src/bin/08.rs b/src/bin/08.rs index 4b45989..14c24ad 100644 --- a/src/bin/08.rs +++ b/src/bin/08.rs @@ -1,18 +1,19 @@ +use aoc::*; use itertools::Itertools; use std::cmp::Reverse; use std::collections::HashSet; +const INPUT: &str = include_str!("../../input/08"); + fn main() { - let input = include_str!("../../input/08"); - println!("Part 1: {}", part1(input, 1000)); - println!("Part 2: {}", part2(input)); + println!("Part 1: {}", part1(INPUT, 1000)); + println!("Part 2: {}", part2(INPUT)); } #[test] fn example() { - let input = include_str!("../../input/08-test"); - assert_eq!(part1(input, 10), 40); - assert_eq!(part2(input), 25272); + assert_eq!(part1(include_str!("../../input/08-test"), 10), 40); + assert_example!(part2, "08-test", 25272); } fn part1(input: &str, n: usize) -> usize { diff --git a/src/bin/09.rs b/src/bin/09.rs index ef0c0fd..6c20878 100644 --- a/src/bin/09.rs +++ b/src/bin/09.rs @@ -1,16 +1,19 @@ +use aoc::*; use glam::I64Vec2; use itertools::Itertools; use rayon::prelude::*; use std::collections::HashMap; +const INPUT: &str = include_str!("../../input/09"); + fn main() { - let input = include_str!("../../input/09"); - println!("Part 1: {}", part1(input)); - println!("Part 2: {}", part2(input)); + println!("Part 1: {}", part1(INPUT)); + println!("Part 2: {}", part2(INPUT)); } #[test] fn example() { + assert_example!(part1, "09-test", 50); assert!(Line(I64Vec2::new(0, 10), I64Vec2::ZERO).contains(I64Vec2::new(0, 0))); assert!(Line(I64Vec2::new(0, 10), I64Vec2::ZERO).contains(I64Vec2::new(0, 10))); assert!(Line(I64Vec2::new(0, 10), I64Vec2::ZERO).contains(I64Vec2::new(0, 5))); @@ -19,10 +22,7 @@ fn example() { assert!(!Line(I64Vec2::ONE, I64Vec2::ONE).contains(I64Vec2::new(1, 10))); assert!(Line(I64Vec2::ONE, I64Vec2::ONE).contains(I64Vec2::new(1, 1))); assert!(!Line(I64Vec2::ONE, I64Vec2::ONE).contains(I64Vec2::ZERO)); - - let input = include_str!("../../input/09-test"); - assert_eq!(part1(input), 50); - assert_eq!(part2(input), 24); + assert_example!(part2, "09-test", 24); } fn part1(input: &str) -> u64 { diff --git a/src/bin/10.rs b/src/bin/10.rs index cb5d441..d73376f 100644 --- a/src/bin/10.rs +++ b/src/bin/10.rs @@ -1,17 +1,18 @@ +use aoc::*; use microlp::{ComparisonOp, OptimizationDirection, Problem}; use std::collections::VecDeque; +const INPUT: &str = include_str!("../../input/10"); + fn main() { - let input = include_str!("../../input/10"); - println!("Part 1: {}", part1(input)); - println!("Part 2: {}", part2(input)); + println!("Part 1: {}", part1(INPUT)); + println!("Part 2: {}", part2(INPUT)); } #[test] fn example() { - let input = include_str!("../../input/10-test"); - assert_eq!(part1(input), 7); - assert_eq!(part2(input), 33); + assert_example!(part1, "10-test", 7); + assert_example!(part2, "10-test", 33); } fn part1(input: &str) -> usize { diff --git a/src/bin/12.rs b/src/bin/12.rs deleted file mode 100644 index e0974d5..0000000 --- a/src/bin/12.rs +++ /dev/null @@ -1,82 +0,0 @@ -use aoc::*; -use glam::USizeVec2; -use itertools::Itertools; - -fn main() { - let input = include_str!("../../input/12"); - println!("Part 1: {}", part1(input)); -} - -fn part1(input: &str) -> usize { - let (presents, regions) = parse_input(input); - regions.into_iter().filter(|r| r.fits(&presents)).count() -} - -fn parse_input(input: &str) -> (Vec, Vec) { - let chunks = input.split("\n\n").collect_vec(); - let (presents, regions) = chunks.split_at(chunks.len() - 1); - let presents = presents.iter().map(|p| Present::parse(p)).collect(); - let regions = regions - .iter() - .flat_map(|chunk| chunk.lines()) - .map(Region::parse) - .collect(); - (presents, regions) -} - -#[derive(Copy, Clone)] -struct Present { - area: usize, -} - -impl Present { - fn parse(input: &str) -> Self { - let area = input - .lines() - .skip(1) - .flat_map(|line| line.chars()) - .filter(|&c| c == '#') - .count(); - Self { area } - } -} - -struct Region { - size: USizeVec2, - presents: Vec, -} - -impl Region { - fn fits(&self, presents: &[Present]) -> bool { - let total_present_area: usize = self - .pick_presents(presents) - .into_iter() - .map(|(n, present)| n * present.area) - .sum(); - total_present_area <= self.area() - } - - fn pick_presents(&self, presents: &[Present]) -> Vec<(usize, Present)> { - self.presents - .iter() - .copied() - .enumerate() - .map(|(i, n)| (n, presents[i])) - .collect() - } - - fn area(&self) -> usize { - self.size.x * self.size.y - } - - fn parse(line: &str) -> Self { - let (size, presents) = line.split_once(": ").unwrap(); - - let (x, y) = size.split_once('x').unwrap(); - let size = USizeVec2::new(x.parse().unwrap(), y.parse().unwrap()); - - let presents = parse_ws_separated(presents).collect(); - - Self { size, presents } - } -} diff --git a/src/lib.rs b/src/lib.rs index 2335521..a35acb7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,6 +93,21 @@ where a / gcd * b } +/// Given a function and a name of a file in the `input` directory, +/// assert that the function applied to the contents of the file returns the expected result. +#[macro_export] +macro_rules! assert_example { + ($solve:ident, $file:expr, $expected:expr) => { + assert_eq!( + $solve(include_str!(concat!("../../input/", $file))), + $expected, + "{}, {}", + stringify!($solve), + $file, + ) + }; +} + /// 4 directions. Start pointing right and go CCW. pub const DIRECTIONS4: [IVec2; 4] = [ IVec2::new(1, 0),