From bd5d5ae9013afddf0fe1087131c68277cd0a658c Mon Sep 17 00:00:00 2001 From: Gabe Venberg Date: Tue, 12 Dec 2023 14:14:56 -0600 Subject: [PATCH] day11 --- Cargo.lock | 9 + aoc_libs/src/distances.rs | 3 + aoc_libs/src/lib.rs | 1 + aoc_libs/src/points.rs | 24 ++- days/day06/src/parse.rs | 13 -- days/day11/Cargo.toml | 11 ++ days/day11/src/input.txt | 140 ++++++++++++++ days/day11/src/main.rs | 14 ++ days/day11/src/parse.rs | 388 ++++++++++++++++++++++++++++++++++++++ days/day11/src/part1.rs | 27 +++ days/day11/src/part2.rs | 28 +++ 11 files changed, 642 insertions(+), 16 deletions(-) create mode 100644 aoc_libs/src/distances.rs create mode 100644 days/day11/Cargo.toml create mode 100644 days/day11/src/input.txt create mode 100644 days/day11/src/main.rs create mode 100644 days/day11/src/parse.rs create mode 100644 days/day11/src/part1.rs create mode 100644 days/day11/src/part2.rs diff --git a/Cargo.lock b/Cargo.lock index ec4c3d7..3a465fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,15 @@ dependencies = [ "aoc_libs", ] +[[package]] +name = "day11" +version = "0.1.0" +dependencies = [ + "aoc_libs", + "collection_literals", + "itertools", +] + [[package]] name = "either" version = "1.9.0" diff --git a/aoc_libs/src/distances.rs b/aoc_libs/src/distances.rs new file mode 100644 index 0000000..a6219ad --- /dev/null +++ b/aoc_libs/src/distances.rs @@ -0,0 +1,3 @@ +pub trait Distances{ + fn taxicab_distance(&self, other: &Self)->usize; +} diff --git a/aoc_libs/src/lib.rs b/aoc_libs/src/lib.rs index 6e52000..b87b103 100644 --- a/aoc_libs/src/lib.rs +++ b/aoc_libs/src/lib.rs @@ -1,3 +1,4 @@ pub mod points; pub mod range; pub mod misc; +pub mod distances; diff --git a/aoc_libs/src/points.rs b/aoc_libs/src/points.rs index 74a92c6..5dd921c 100644 --- a/aoc_libs/src/points.rs +++ b/aoc_libs/src/points.rs @@ -1,3 +1,5 @@ +use crate::distances::Distances; + #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)] pub struct Point { pub x: isize, @@ -16,6 +18,12 @@ impl Point { } } +impl Distances for Point { + fn taxicab_distance(&self, other: &Self) -> usize { + self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + } +} + impl std::ops::Add for Point { type Output = Point; @@ -62,7 +70,7 @@ impl std::ops::Neg for Point { } /// an unsigned point in 2d space -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct UPoint { pub x: usize, pub y: usize, @@ -80,6 +88,12 @@ impl UPoint { } } +impl Distances for UPoint { + fn taxicab_distance(&self, other: &Self) -> usize { + self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + } +} + impl std::ops::Add for UPoint { type Output = UPoint; @@ -184,7 +198,9 @@ where } } -impl std::ops::IndexMut for FourQuadrantMatrix<{ X }, { Y }, T> { +impl std::ops::IndexMut + for FourQuadrantMatrix<{ X }, { Y }, T> +{ fn index_mut(&mut self, index: Point) -> &mut Self::Output { let upoint = index .to_upoint(&self.zero_coord) @@ -193,7 +209,9 @@ impl std::ops::IndexMut for FourQuadra } } -impl std::ops::Index for FourQuadrantMatrix<{ X }, { Y }, T> { +impl std::ops::Index + for FourQuadrantMatrix<{ X }, { Y }, T> +{ type Output = T; fn index(&self, index: Point) -> &Self::Output { diff --git a/days/day06/src/parse.rs b/days/day06/src/parse.rs index 979157a..b99a455 100644 --- a/days/day06/src/parse.rs +++ b/days/day06/src/parse.rs @@ -115,19 +115,6 @@ mod tests { assert_eq!(input.num_ways_to_win(), 71503); } - #[test] - fn test_distance_given_charge_time() { - let input = Race { time: 7, record: 9 }; - assert_eq!(input.distance_given_charge_time(0), 0); - assert_eq!(input.distance_given_charge_time(1), 6); - assert_eq!(input.distance_given_charge_time(2), 10); - assert_eq!(input.distance_given_charge_time(3), 12); - assert_eq!(input.distance_given_charge_time(4), 12); - assert_eq!(input.distance_given_charge_time(5), 10); - assert_eq!(input.distance_given_charge_time(6), 6); - assert_eq!(input.distance_given_charge_time(7), 0); - } - #[test] fn test_parse_part2() { let input = concat!("Time: 7 15 30\n", "Distance: 9 40 200\n",); diff --git a/days/day11/Cargo.toml b/days/day11/Cargo.toml new file mode 100644 index 0000000..73faadb --- /dev/null +++ b/days/day11/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "day11" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true +collection_literals.workspace = true +itertools.workspace = true diff --git a/days/day11/src/input.txt b/days/day11/src/input.txt new file mode 100644 index 0000000..7e78179 --- /dev/null +++ b/days/day11/src/input.txt @@ -0,0 +1,140 @@ +.#..........#.....................#........................................................#....................................#........... +...................#........................................#......................#........................................................ +...........................................#......#..................#...................................................#.................. +....#......................#...............................................#.........................#.....#......#................#........ +.................................................................#.......................#.................................................. +..............................................................................................................................#............. +.......#........#.............#...................................................#...................................#..................... +.........................#...................................#............................................................................#. +....................#.............#.........#..........................................#...............#.................................... +.....................................................#...............#.............................................................#........ +...........................................................................................................................#................ +..........................................................#.........................................#...............#....................... +..............................................................................................#............................................. +.#........#........................#......#..............................................#..............................#...............#... +...............#......#...............................#.......#.........#......#.............................#.................#............ +...............................#..............#............................................................................................. +............................................................................................................................................ +.........................#.......................................#.......................................................................... +..................#........................#......................................#........................................#................ +..................................................#.......#..............................................#........................#.......#. +...#........#........................#....................................#...............#................................................. +............................................................................................................................................ +.......#........................#....................................................................................#...................... +...............#...........#........................................................................#....................................... +.............................................#................#.........#.............................................................#..... +...........#...........................#................#...........................#....................................................... +..................................................#.......................................#.............#................................... +.....#..................#..........#..............................#.............................#........................................#.. +..............................#...............................................................................................#............. +...................................................................................................................#........................ +..............#..........................................#.............#...........................#..............................#......... +...#...................................#.........................................#.......................................................... +..................#...................................................................#................................................#.... +..........................#...................................#.........................................#................................... +............................................................................................................................................ +.........#...........#..........#..........................................#....................#..............#........#.....#...........#. +....................................................#....................................................................................... +.............................................#.............................................................................................. +......................................#..................#..............................#...........#.......#............................... +............................#..................................#..............#............................................................. +...............#............................................................................................................................ +...........................................#............................#.......................#........................................... +.....#..............#.................................................................................#...........................#......... +............................................................................................................................................ +........................................#..........#.................#..........................................#........................... +.............................................#.................................#...........#................................................ +...............................#.......................#...........................................#.......#....................#........... +#........#.............#...............................................................................................#...................# +.....................................#........................#..........#.........#........................................................ +.................#............................................................................#............................................. +..........................#.......................................#.................................................#....................... +.....................................................#...................................#....................................#............. +..#......................................................................................................................................... +.............#.....#.......................#.............#....................................................#........................#.... +......#........................................................................................#............................................ +.................................#.................................#........................................................................ +.................................................................................#.......................#................................#. +#.....................................................#...................................................................#.....#........... +.........#..................................................#......................................#........................................ +..............................#.............#.................................................................#.......#..................... +........................#............................................................#......#................................#.............. +.............#.............................................................................................................................. +.....#........................................................#............#..........................#...........................#......... +...........................#......#.................................................................................#...................#... +.........#.....................................#...............................#............................................................ +..................#.......................................#.......#................................#........................................ +...............................#.....................#...................................#................................#................. +..............#..........................#.............................#............#.....................#.....................#.........#. +.................................................................................................................#.......................... +......#..................................................................................................................................... +...........#.............#.........#........................................................................................................ +...................................................................#..............#..................#...................................... +..................#...........................................................................................#............................. +........#.................................#..............#.................................................................#..........#..... +...#.....................................................................#..............#.......#........................................... +............................................................................................................................................ +............................................................................................................................................ +.................................#................#..........................................................#...............#.............# +..............#............................................................#................................................................ +......#.....................#..........................#........#.....#............#..............#......................................... +....................#..................................................................................#..................#................. +....................................#.........#........................................................................................#.... +..........................................................#..............#.................................................................. +................#...............................................................................................#.............#............. +............................................................................................................................................ +............................#...................#......#.............#..............................................#....................... +.............#...................................................................................#........................................#. +......................#..........................................................#.......#.................................................. +#...........................................................#............................................................................... +.........#.........................#.................#....................................................#.................#............... +............................................................................................................................................ +...................#.............................................#.....#.................................................................... +........................#.........................#.....................................................................................#... +.....#........................................................................................................................#............. +.......................................#...............................................................#.........#.......................... +............................#...........................#...........#......................#..............................#.......#......... +..#................................#...........#............................................................................................ +.................#..................................#...................#................................................................... +..........#.................................................#................................................#.............................. +.....................#...............................................................................#...................................... +..............#..................#..............................#.............#....................................#.........#........#..... +...#.............................................................................................#.......................................... +............................................#..........................................#.................................................... +.........#...............................................#..............................................................#................... +................#.........#................................................................................................................. +.....#..................................#............................#..............................#........#..................#..........# +...............................#............................................................................................................ +....................................................#........#.............................................................................. +........#..........................#.........#...............................................................................#.............. +....................................................................................................................#....................... +....................#........#......................................#.........#.....#.....#................................................. +................................................................................................................................#.....#..... +...............#..........................................#...............#...............................#................................. +...#..............................#......................................................................................................... +........................................................................................#............#....................................#. +............................................................................................................................#............... +...................................................................................#............................#........................... +#........#........#........#..........#.........#........................................................................................... +.............................................................#..............................#............................#.................. +................................#.......................#................................................................................... +.......................#................................................#...............#.........#..................#................#..... +............#..................................................................#........................#................................... +............................................................................................................................................ +......#.....................#.......#......#..............#......#.......................................................................... +.....................#...................................................................................................................... +................................#................................................#.............#...........................#.............#.. +..............................................................................................................#............................. +............#............#..........................................................................#.............................#......... +.....#...........#.....................#.............................#.....#........................................#....................... +................................................#...........#..........................#.................................................... +............................................................................................................................................ +#..........................#.....#................................................................#......................................#.. +..........................................#.................................................................#.............#................. +................#.........................................................#................................................................. +.......#..............................#..............................................#..........................................#........... +........................#...................................#............................................................................... +............................................................................................................................#............... +..............................#.....................#.............................#...........#.................#........................... +...............................................#................#.....#................................................#.................... +...................#...................#.................#.................#.........................#...................................... diff --git a/days/day11/src/main.rs b/days/day11/src/main.rs new file mode 100644 index 0000000..456385c --- /dev/null +++ b/days/day11/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/days/day11/src/parse.rs b/days/day11/src/parse.rs new file mode 100644 index 0000000..01d4a4d --- /dev/null +++ b/days/day11/src/parse.rs @@ -0,0 +1,388 @@ +use std::collections::HashSet; + +use aoc_libs::distances::Distances; +use aoc_libs::points::UPoint; +use itertools::Itertools; + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Space { + Galaxy, + Space, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct SparseSpace { + galaxies: HashSet, + empty_rows: HashSet, + empty_columns: HashSet, +} + +impl SparseSpace { + pub fn get_distance_between_galaxies( + &self, + galaxy1: &UPoint, + galaxy2: &UPoint, + expantion: &usize, + ) -> usize { + // println!("distance between {:?} and {:?}", galaxy1, galaxy2); + + //get unexpanded distance. + let mut distance = galaxy1.taxicab_distance(galaxy2); + // println!("unexpanded distance is {}", distance); + + //expand rows + for y in galaxy1.y.min(galaxy2.y)+1..galaxy1.y.max(galaxy2.y) { + if self.empty_rows.contains(&y) { + // println!("expanding row {}", y); + distance += expantion + } + } + + //expand columns. + for x in galaxy1.x.min(galaxy2.x)+1..galaxy1.x.max(galaxy2.x) { + if self.empty_columns.contains(&x) { + // println!("expanding col {}", x); + distance += expantion + } + } + distance + } + + pub fn get_sum_of_distances(&self, expantion: usize) -> usize { + self.galaxies + .iter() + .combinations(2) + // .inspect(|pair| println!("{:?}", pair)) + .map(|pair| self.get_distance_between_galaxies(pair[0], pair[1], &expantion)) + // .inspect(|distance| println!("{:?}", distance)) + .sum() + } +} + +impl From>> for SparseSpace { + fn from(value: Vec>) -> Self { + let mut galaxies: HashSet = HashSet::new(); + let mut empty_rows: HashSet = HashSet::new(); + let mut empty_columns: HashSet = HashSet::new(); + //find all galaxies and empty rows. + for (y, row) in value.iter().enumerate() { + let mut has_galaxy = false; + for (x, space) in row.iter().enumerate() { + if *space == Space::Galaxy { + has_galaxy = true; + galaxies.insert(UPoint { x, y }); + }; + } + if !has_galaxy { + empty_rows.insert(y); + }; + } + + //find all empty columns + for x in 0..value[0].len() { + let mut has_galaxy = false; + for y in 0..value.len() { + if value[y][x] == Space::Galaxy { + has_galaxy = true; + } + } + if !has_galaxy { + empty_columns.insert(x); + }; + } + + SparseSpace { + galaxies, + empty_rows, + empty_columns, + } + } +} + +pub fn parse(input: &str) -> SparseSpace { + parse_to_space(input).into() +} + +pub fn parse_to_space(input: &str) -> Vec> { + input + .lines() + .map(|l| { + l.chars() + .map(|c| match c { + '#' => Space::Galaxy, + '.' => Space::Space, + _ => panic!("unexpected char {}", c), + }) + .collect() + }) + .collect() +} + +#[cfg(test)] +mod tests { + use collection_literals::collection; + + use super::*; + + #[test] + fn test_get_sum_of_distances() { + let tested = SparseSpace { + galaxies: collection! { + UPoint { x: 0, y: 2 }, + UPoint { x: 0, y: 9 }, + UPoint { x: 1, y: 5 }, + UPoint { x: 3, y: 0 }, + UPoint { x: 4, y: 9 }, + UPoint { x: 6, y: 4 }, + UPoint { x: 7, y: 1 }, + UPoint { x: 7, y: 8 }, + UPoint { x: 9, y: 6 } + }, + empty_rows: collection! {3, 7}, + empty_columns: collection! {2, 5, 8}, + }; + assert_eq!(tested.get_sum_of_distances(1), 374) + } + + #[test] + fn test_get_distance_between_galaxies() { + let tested = SparseSpace { + galaxies: collection! { + UPoint { x: 0, y: 2 }, + UPoint { x: 0, y: 9 }, + UPoint { x: 1, y: 5 }, + UPoint { x: 3, y: 0 }, + UPoint { x: 4, y: 9 }, + UPoint { x: 6, y: 4 }, + UPoint { x: 7, y: 1 }, + UPoint { x: 7, y: 8 }, + UPoint { x: 9, y: 6 } + }, + empty_rows: collection! {3, 7}, + empty_columns: collection! {2, 5, 8}, + }; + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 4, y: 9 }, + &UPoint { x: 1, y: 5 }, + &1 + ), + 9 + ); + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 7, y: 8 }, + &UPoint { x: 0, y: 3 }, + &1 + ), + 15 + ); + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 0, y: 2 }, + &UPoint { x: 9, y: 6 }, + &1 + ), + 17 + ); + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 0, y: 9 }, + &UPoint { x: 4, y: 9 }, + &1 + ), + 5 + ); + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 3, y: 0 }, + &UPoint { x: 6, y: 4 }, + &1 + ), + 9 + ); + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 7, y: 8 }, + &UPoint { x: 7, y: 8 }, + &1 + ), + 0 + ); + } + + #[test] + fn test_parse() { + let input = concat!( + "...#......\n", + ".......#..\n", + "#.........\n", + "..........\n", + "......#...\n", + ".#........\n", + ".........#\n", + "..........\n", + ".......#..\n", + "#...#.....\n", + ); + assert_eq!( + parse(input), + SparseSpace { + galaxies: collection! { + UPoint { x: 0, y: 2 }, + UPoint { x: 0, y: 9 }, + UPoint { x: 1, y: 5 }, + UPoint { x: 3, y: 0 }, + UPoint { x: 4, y: 9 }, + UPoint { x: 6, y: 4 }, + UPoint { x: 7, y: 1 }, + UPoint { x: 7, y: 8 }, + UPoint { x: 9, y: 6 } + }, + empty_rows: collection! {3, 7}, + empty_columns: collection! {2, 5, 8} + } + ) + } + + #[test] + fn test_parse_to_space() { + let input = concat!( + "...#......\n", + ".......#..\n", + "#.........\n", + "..........\n", + "......#...\n", + ".#........\n", + ".........#\n", + "..........\n", + ".......#..\n", + "#...#.....\n", + ); + assert_eq!( + parse_to_space(input), + vec![ + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space + ], + vec![ + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space + ], + vec![ + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ] + ] + ); + } +} diff --git a/days/day11/src/part1.rs b/days/day11/src/part1.rs new file mode 100644 index 0000000..1e36057 --- /dev/null +++ b/days/day11/src/part1.rs @@ -0,0 +1,27 @@ +use crate::parse::*; + +pub fn part1(input: &SparseSpace) -> usize { + input.get_sum_of_distances(1) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = concat!( + "...#......\n", + ".......#..\n", + "#.........\n", + "..........\n", + "......#...\n", + ".#........\n", + ".........#\n", + "..........\n", + ".......#..\n", + "#...#.....\n", + ); + assert_eq!(part1(&parse(input)), 374) + } +} diff --git a/days/day11/src/part2.rs b/days/day11/src/part2.rs new file mode 100644 index 0000000..97e5a45 --- /dev/null +++ b/days/day11/src/part2.rs @@ -0,0 +1,28 @@ +use crate::parse::*; + +pub fn part2(input: &SparseSpace) -> usize { + input.get_sum_of_distances(999_999) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let input = concat!( + "...#......\n", + ".......#..\n", + "#.........\n", + "..........\n", + "......#...\n", + ".#........\n", + ".........#\n", + "..........\n", + ".......#..\n", + "#...#.....\n", + ); + assert_eq!(parse(input).get_sum_of_distances(9), 1030); + assert_eq!(parse(input).get_sum_of_distances(99), 8410); + } +}