diff --git a/2023/day11_cosmic_expansion/Cargo.toml b/2023/day11_cosmic_expansion/Cargo.toml new file mode 100644 index 0000000..eb507f1 --- /dev/null +++ b/2023/day11_cosmic_expansion/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "day11_cosmic_expansion" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] + +[dev-dependencies] +criterion = "0.5.1" + +[[bench]] +name = "test_benchmark" +harness = false diff --git a/2023/day11_cosmic_expansion/challenge.txt b/2023/day11_cosmic_expansion/challenge.txt new file mode 100644 index 0000000..ead3d17 --- /dev/null +++ b/2023/day11_cosmic_expansion/challenge.txt @@ -0,0 +1,130 @@ +You continue following signs for "Hot Springs" and eventually come across an [observatory](https://en.wikipedia.org/wiki/Observatory). The Elf within turns out to be a researcher studying cosmic expansion using the giant telescope here. + +He doesn't know anything about the missing machine parts; he's only visiting for this research project. However, he confirms that the hot springs are the next-closest area likely to have people; he'll even take you straight there once he's done with today's observation analysis. + +Maybe you can help him with the analysis to speed things up? + +The researcher has collected a bunch of data and compiled the data into a single giant *image* (your puzzle input). The image includes *empty space* (`.`) and *galaxies* (`#`). For example: + +``` +...#...... +.......#.. +#......... +.......... +......#... +.#........ +.........# +.......... +.......#.. +#...#..... + +``` + +The researcher is trying to figure out the sum of the lengths of the *shortest path between every pair of galaxies*. However, there's a catch: the universe expanded in the time it took the light from those galaxies to reach the observatory. + +Due to something involving gravitational effects, *only some space expands*. In fact, the result is that *any rows or columns that contain no galaxies* should all actually be twice as big. + +In the above example, three columns and two rows contain no galaxies: + +``` + v v v + ...#...... + .......#.. + #......... +>..........< + ......#... + .#........ + .........# +>..........< + .......#.. + #...#..... + ^ ^ ^ + +``` + +These rows and columns need to be *twice as big*; the result of cosmic expansion therefore looks like this: + +``` +....#........ +.........#... +#............ +............. +............. +........#.... +.#........... +............# +............. +............. +.........#... +#....#....... + +``` + +Equipped with this expanded universe, the shortest path between every pair of galaxies can be found. It can help to assign every galaxy a unique number: + +``` +....1........ +.........2... +3............ +............. +............. +........4.... +.5........... +............6 +............. +............. +.........7... +8....9....... + +``` + +In these 9 galaxies, there are *36 pairs*. Only count each pair once; order within the pair doesn't matter. For each pair, find any shortest path between the two galaxies using only steps that move up, down, left, or right exactly one `.` or `#` at a time. (The shortest path between two galaxies is allowed to pass through another galaxy.) + +For example, here is one of the shortest paths between galaxies `5` and `9`: + +``` +....1........ +.........2... +3............ +............. +............. +........4.... +.5........... +.##.........6 +..##......... +...##........ +....##...7... +8....9....... + +``` + +This path has length `*9*` because it takes a minimum of *nine steps* to get from galaxy `5` to galaxy `9` (the eight locations marked `#` plus the step onto galaxy `9` itself). Here are some other example shortest path lengths: + +* Between galaxy `1` and galaxy `7`: 15 +* Between galaxy `3` and galaxy `6`: 17 +* Between galaxy `8` and galaxy `9`: 5 + +In this example, after expanding the universe, the sum of the shortest path between all 36 pairs of galaxies is `*374*`. + +Expand the universe, then find the length of the shortest path between every pair of galaxies. *What is the sum of these lengths?* + +Your puzzle answer was `10228230`. + +\--- Part Two --- +---------- + +The galaxies are much *older* (and thus much *farther apart*) than the researcher initially estimated. + +Now, instead of the expansion you did before, make each empty row or column *one million times* larger. That is, each empty row should be replaced with `1000000` empty rows, and each empty column should be replaced with `1000000` empty columns. + +(In the example above, if each empty row or column were merely `10` times larger, the sum of the shortest paths between every pair of galaxies would be `*1030*`. If each empty row or column were merely `100` times larger, the sum of the shortest paths between every pair of galaxies would be `*8410*`. However, your universe will need to expand far beyond these values.) + +Starting with the same initial image, expand the universe according to these new rules, then find the length of the shortest path between every pair of galaxies. *What is the sum of these lengths?* + +Your puzzle answer was `447073334102`. + +Both parts of this puzzle are complete! They provide two gold stars: \*\* + +At this point, you should [return to your Advent calendar](/2023) and try another puzzle. + +If you still want to see it, you can [get your puzzle input](11/input). \ No newline at end of file diff --git a/2023/day11_cosmic_expansion/src/lib.rs b/2023/day11_cosmic_expansion/src/lib.rs new file mode 100644 index 0000000..341a01a --- /dev/null +++ b/2023/day11_cosmic_expansion/src/lib.rs @@ -0,0 +1,75 @@ +use core::fmt::Display; +use std::num::ParseIntError; + +#[derive(Debug, PartialEq, Eq)] +pub enum ParseError<'a> { + ParseIntError(std::num::ParseIntError), + LineMalformed(&'a str), +} + +impl From for ParseError<'_> { + fn from(value: ParseIntError) -> Self { + Self::ParseIntError(value) + } +} + +impl Display for ParseError<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::LineMalformed(v) => write!(f, "Line is malformed: {v}"), + Self::ParseIntError(e) => write!(f, "Unable to parse into integer: {e}"), + } + } +} + +fn galaxies_from_image(input: &str, expansion: usize) -> Vec<(usize, usize)> { + let mut row = 0; + let mut galaxies = Vec::new(); + input.lines().for_each(|line| { + let curr_line: Vec<_> = line.match_indices('#').collect(); + if curr_line.is_empty() { + row += expansion; + } else { + curr_line.iter().for_each(|(col, _)| galaxies.push((row, *col))); + row += 1; + } + }); + galaxies.sort_by(|a, b| b.1.cmp(&a.1)); + (0..galaxies.len()-1).for_each(|idx| { + let diff = galaxies[idx].1 - galaxies[idx+1].1; + if diff > 1 { + galaxies.iter_mut().take(idx+1).for_each(|(_row, col)| *col += (diff-1)*expansion-1); + } + }); + galaxies +} + +pub fn run(input: &str) -> Result<(usize, usize), ParseError> { + let galaxies: Vec<_> = galaxies_from_image(input, 2); + let first = galaxies.iter().enumerate().map(|(idx, (y1, x1))| galaxies.iter().skip(idx+1).map(|(y2, x2)| y1.abs_diff(*y2) + x1.abs_diff(*x2)).sum::()).sum(); + let galaxies: Vec<_> = galaxies_from_image(input, 1000000); + let second = galaxies.iter().enumerate().map(|(idx, (y1, x1))| galaxies.iter().skip(idx+1).map(|(y2, x2)| y1.abs_diff(*y2) + x1.abs_diff(*x2)).sum::()).sum(); + Ok((first, second)) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::fs::read_to_string; + + fn read_file(name: &str) -> String { + read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string() + } + + #[test] + fn test_sample() { + let sample_input = read_file("tests/sample_input"); + assert_eq!(run(&sample_input), Ok((374, 82000210))); + } + + #[test] + fn test_challenge() { + let challenge_input = read_file("tests/challenge_input"); + assert_eq!(run(&challenge_input), Ok((10228230, 447073334102))); + } +} diff --git a/2023/day11_cosmic_expansion/tests/challenge_input b/2023/day11_cosmic_expansion/tests/challenge_input new file mode 100644 index 0000000..8b0a495 --- /dev/null +++ b/2023/day11_cosmic_expansion/tests/challenge_input @@ -0,0 +1,140 @@ +.....................................................................................#......#............................................... +..#.....#.................................................................#........................#........................................ +...............................#...............................................................................#.....#...................... +.................................................#.............#...............................#...................................#........ +..............#......#.................#...............#............#.............#..........................................#.............. +.........................................................................................#.................#...............................# +.#.......................................................................................................................................... +..........................#......#............................................#......#.................................#.................... +.................................................................................................#.......................................... +.........................................#..........#..........#............................................................#............... +......#.....#......#..........................#........................#.................................................................... +....................................#.........................................................................#..........................#.. +..................................................................................#......................................................... +...................................................................................................................#........................ +.................................................................#........................................#................................. +.............................#..............................#..........................#.......#............................................ +..........................................#.....#.............................#............................................................. +#..................#..................................................................................................................#..... +....................................#...................#..........................#...........................#..............#............. +........#................#...................#.............................................................................................# +...............................#....................#...........................................#........................................... +.......................................#..............................................#..................................................... +........................................................................#........#...........................#.............................. +..................................#........#...................#........................................#.........#.................#....... +#................#........................................................................................................#................. +.........#.......................................#...............................................#.............................#........#... +...............................................................................................................#............................ +.........................................................................................#.................................................. +...........................................................#..................................#..........#...........................#...... +......#.........................#..........................................................................................#................ +....................#.....................#.......#...............................#.................................#....................... +..........................#..............................................#.................................................................. +..........#..........................#.......................#...................................#..............#..............#...........# +......................................................#..................................................................................... +............................................................................................................................................ +#...............................................#................#............................#............................................. +..................#......................#............................#................................#................................#... +............................................................................................................................................ +....................................................#....................................#.............................#.................... +..............#...................#................................#..........#..............................#.............................# +............................#...............................................................................................#............... +....#.................#.....................................#..........#............................................................#....... +......................................................#..................................................................................... +...........#..............................#.................................................#..........#.................#.................. +.................................#..............#................#..........#.......#....................................................... +...................................................................................................................#..............#......... +#...........................................................................................................#............................... +........#.......#............................................................................................................#.............. +............................#.....................#..........#......................................#.....................................#. +.....................................#.................................................#........................#........................... +.........................................................................................................................#...........#...... +.......................#.............................#........................#............................................................. +..............#...............................#.................#..................#........#............................................... +...#......................................................................#.................................#..............................# +...................#..................#.............................................................................#........#.............. +............................................................................................................................................ +.........................#.........................#........................................................................................ +......#......#.............................................#.............................#............#..................................... +.................................#......................................#................................................................... +.........................................#........................#..............................#.................#..............#......... +............................................................................................................................................ +......................................................#.................................................#..............#..................#. +......................#......#...............#...................................#............................#............................. +....#...........#.................#............................................................#...............................#............ +..........................................................................#..........................#...................................... +..........................................#................................................#...............................#............#... +................................................................................................................#........................... +..........#....................................#...................................................................................#........ +................................#....................#..............................................................#....................... +......#.......................................................#...............................#............................................. +#.......................#.....................................................................................................#............. +.................#...................#...........................................#..........................#............................... +.....................................................................#....................#................................................. +..............................#.................#.......#.........................................#......................................... +..#........................................................................#....................................#.........#................. +...........#............................#..........................................#.............................................#.......... +......#.............................................................................................................#.....................#. +........................................................................................................#................................... +..............#...................#.........#............................................................................................... +........................................................#.............#..........#.....#..........#............................#............ +.........#......................................................#...........................#............................................... +.........................................#...................................#.................................#............................ +............................................................................................................................................ +................#...................................................................#.................#..................#.................. +.................................#..........................#.............#....................#................................#..........# +...#........................#.........................................................................................................#..... +.................................................#......................................#.....................#......#...................... +...........................................#.........................#........#............................................................. +........#......#...................................................................................................................#.....#.. +.#..................#..................................#.........#.......................................................................... +..................................#.....#.................................#................................................................. +...................................................#.................................#...................................................... +............................................................#............................................................................... +.............................................#......................#..........#............#.........................#......#.............. +................................#...................................................................#....................................... +.....................................................#..................#......................................#............................ +...#......................#.....................................................................................................#........... +...........#...........................................................................#..............................................#..... +................#..................................................#..............................................#......................... +.......................#......................................................................#............................................. +................................#........#.........#.....................#.....#......................#..................................... +.#.......................................................................................................................................... +........................................................#................................#...................#..................#........... +.....................................#........#.................................................#.......................................#... +.........#...........#...................................................................................................................... +....................................................#.............................................................#.................#....... +.............#............#........................................#.............#.....................#...................#...............# +..................#....................#.................................#.............#.................................................... +................................................#........................................................................................... +.......................#...............................................................................................#.................... +....#..........................................................#.....#..............#...........................................#........... +...............................................................................................#..................#.......................#. +.........#...................#............................................#................................................................. +.............................................................................................................#..............#......#........ +...........................................................................................#................................................ +.#...........................................................#.............................................................................. +..............#..............................#........................................#.............#....................................... +....................................#..............#..............#.........#.............................#.............#.............#..... +....................#............................................................................................#.......................... +.........................................................................................#.................................................. +...........#............................#................#....................................................................#............. +.....#......................................................................................................#............................... +..................................#................................................#........#.............................................#. +.#................#......#...........................................................................#...................................... +..............................................#.......................#................#............................................#....... +.........#............................#........................#..........................................#.....#......#.................... +..............................................................................................#............................................. +........................................................................................................................................#... +..........................#........................#...............#................................#............................#.......... +..#........................................#............#............................................................#...................... +...............................#.....#........................................#.......#......................................#.............. +.......................................................................................................#.................................... +.....................................................#..............................................................................#....... +........#......................................#...........................#.............................................#.................# +...................#.....#......................................#.............................#............................................. +............#.........................#......................................................................#.......#.................#.... +..............................#...................................................#......................................................... +............................................#.........................................................#..................................... +.......#..........................#................#.....#.............#.................................................................... +..................#.........................................................#.............#.......................................#......... diff --git a/2023/day11_cosmic_expansion/tests/sample_input b/2023/day11_cosmic_expansion/tests/sample_input new file mode 100644 index 0000000..986aad4 --- /dev/null +++ b/2023/day11_cosmic_expansion/tests/sample_input @@ -0,0 +1,10 @@ +...#...... +.......#.. +#......... +.......... +......#... +.#........ +.........# +.......... +.......#.. +#...#.....