diff --git a/2023/aoc2023/Cargo.lock b/2023/aoc2023/Cargo.lock index 2c136ef..3024601 100644 --- a/2023/aoc2023/Cargo.lock +++ b/2023/aoc2023/Cargo.lock @@ -190,6 +190,7 @@ dependencies = [ name = "day11" version = "0.1.0" dependencies = [ + "itertools", "lube", ] diff --git a/2023/aoc2023/day11/Cargo.toml b/2023/aoc2023/day11/Cargo.toml index 2440c2b..d587bd8 100644 --- a/2023/aoc2023/day11/Cargo.toml +++ b/2023/aoc2023/day11/Cargo.toml @@ -9,3 +9,4 @@ description.workspace = true [dependencies] lube = { path = "../lube" } +itertools = { workspace = true } diff --git a/2023/aoc2023/day11/README.md b/2023/aoc2023/day11/README.md index 9d5e54a..90f5f21 100644 --- a/2023/aoc2023/day11/README.md +++ b/2023/aoc2023/day11/README.md @@ -4,8 +4,18 @@ Link: ## Part 1 -*TBD* +First and foremost we need a method for "expanding the universe", which is *probably* best done through just some mathematical equation after identifying those rows and columns, rather than actually adjusting the input grid. But where's the fun in that? + +It's a simple matter of `.clone()`ing and `.push()`ing something onto an existing vec, so handling rows is simple. Columns are less simple, of course, but we don't need to worry about them much: just transpose the grid and then perform the same push operation on the new "rows". + +After that, search for all galaxies, determining their positions in the grid; then use [`itertools.combination`](https://docs.rs/itertools/latest/itertools/trait.Itertools.html#method.combinations) to produce the various points we need to worry about. From there it's a simple matter of calculating their distances (essentially `abs(x1 - x2) + abs(y1 - y2)`), and then summing that value. ## Part 2 -*TBD* +Sure enough, performing the whole insert and transpose ain't gonna cut it: we can't go shoving 1_000_000 rows in every time we find something. We'd quickly run out of memory! + +Instead, we'll need to identify those rows and cols separately as being empty. I think then we can test if the range between, say, `x1..x2` includes one or more of those rows. If so, we add `999_999` (accounting for an off-by-one issue) to the distance calculation manually. + +Interestingly, the test cases use `n` of `10` and `100` to demonstrate different values. This leads us to write the func taking an argument; one which could be used to solve the first part in the same way. + +So, while the original did include a `part1.rs` and `part2.rs`, I opted to instead use a `funcs` module to move pieces out of the main module (trying to increase some clarity by reducing the lines of code per file). Then we move the solution from part 2 back to `main.rs`, rename to `fn solve()`, and add the `expansion: u64` variable (in place of `n`). Part 1 is now solved by the same method, and tests are run against all 3 examples. diff --git a/2023/aoc2023/day11/input.txt b/2023/aoc2023/day11/input.txt index e69de29..0723e73 100644 --- a/2023/aoc2023/day11/input.txt +++ b/2023/aoc2023/day11/input.txt @@ -0,0 +1,140 @@ +.......#.....#.....................#.............#.................#.........................#.............................................. +#.....................#.......#.................................................................................#.......#................... +.......................................................................#.........................#..................................#....... +................................................................#..............#..............................................#............. +.........................................#............................................................#....................................# +.................#..................................................#....................................................................... +...........................#...............................................................................#................................ +....#.......#...........................................#..........................#.............................#.......................... +....................#.............#........#................................................................................................ +...................................................#...................................................#...................#................ +.........................#........................................#..................................................#...................... +......#..........#...........................................#...........#............#..................................................... +......................................#..........................................#.........................#.....................#.......... +.#...................#..................................#.......................................#........................................... +............#.................................#.....................#....................................................................... +............................................................................................................................................ +..............................#.....................................................................................#..................#.... +....................................................................................#........#......#....................................... +.........................#.........................#............#...........................................#............................... +.#......#.....#.......................#.................#........................................................#.....#.................... +...........................................................................#.................................................#.............. +...............................................#.......................................#...............#..........................#......... +......................#..................#.................................................................................................. +..........................................................................................................................#................. +......#...........................#.........................................................#........................#...................... +..............................................................................................................................#............. +..#.......................#.................#............................................................................................#.. +..................#....................................................#................#................................................... +....................................................#.....#....................#............................................................ +...............................#............................................................................................................ +..............................................#...............#..........................................................#...........#...... +.#.........#........................#..................................................................#.................................... +..........................................................................#.......................#........................................# +...................#......................................................................#................................................. +.............................................................................................................................#.............. +.....#...................................................................................................................................... +........................................................#........................#.......................................................... +.............................#...............#.....................#.....#............#..................#..............................#... +............................................................................................#......#...........#............................ +.........................#........#...................................................................................#..................... +...........................................................................................................................................# +.....................................................#.....#.................................................................#.............. +#.........................................................................................................#.......................#......... +................#...........................................................#.....................#......................................... +..............................#..............#...................................#.......#...........................#...................... +........#................#.........#............................#............................................#.............#.........#...... +............................................................................................................................................ +.......................................................#...............#.............................#...........................#.......... +.............#.................................#............................................................................................ +............................................................................................................................................ +..#.............................................................................#...........................................#...........#... +............................................................................................................................................ +......................................#..........................................................#................#......................... +............................#................#......#......................#...........#.................................................... +............................................................................................................................................ +....................................................................................................#................#..........#........... +.#............#...................#...............................#........................................#.............................#.. +.........#...............................................................#.................................................................. +.......................#....................#........#...........................................#.......................................... +............................................................#.....................................................#......................... +..............................#.......................................................................#...................#.......#......... +............#.......................#...................#............................#...................................................... +...................................................#......................................#..............................................#.. +.#................#...................................................#........................#............................................ +......#....................................................................#................................#............................... +...............................#....................................................................................#....................... +.........................#.....................#......#.............................................#.................................#..... +............................................................................................................................................ +...............#.....................#....................................................#................................................. +..................................................................................................................#......................... +....#......#.....................................#..............................#............................#............#.....#........... +....................#.............................................#....................#.........#.......................................#.. +.........................................................#..............#.............................#..................................... +............................#...........#...........................................................................#....................... +............................................................................................................................................ +#..................................#...............................................................#..........#............................. +.......#......................................................................................#.................................#.......#... +.....................#....................#...............................#.....#......................................#.................... +................................#..........................#......#....................#..........................#......................... +..............#...................................#........................................................................#...............# +....#....................................................................................................#.................................. +.......................#.................................................................................................................... +......................................#................................#..................#................................................. +.....................................................#............................................#...............................#......... +............................................................................................................................................ +............................................................................................................................................ +....#.................#..................................#.........................#..........................#............................. +.............#........................................................................................#..................#.................. +......................................#............................................................................#........................ +.........#....................................................#.........#............................................................#...... +.............................................................................................#.............................................. +.............................#...........#............................................................................#..................... +#..................#................................................#....................#.......................................#.........# +...................................................................................................#......#................................. +...........#.............................................#...........................#...................................................... +....................................#....................................................................................................... +..................................................#..........#.........#......................#.....................#....................... +.#......#....................................#..............................................................#............................... +.............................#.............................................#................................................................ +.......................#...............................................................................#....................#............... +....................................................#.....................................#...........................................#..... +................#.....................#..................#.................................................................................# +...#.....#..........................................................#................#...................................................... +.............................................#...............#................................#......#...................................... +...............................#...............................................#............................................................ +.............................................................................................................................#.........#.... +.....................#................................................#.................................................#................... +...............#.........................#.......................#..................#....................................................... +.....#......................................................................................................#.......................#....... +....................................#.................#.........................#..................#........................................ +........................................................................................................................................#... +.........#..............#.....................................#........................................#.....................#.............. +...............................................#...................#........................................................................ +......................................#.............#..................................#.....#.......................#...................... +............#.....#...............................................................................#......................................... +...#...................................................................................................................................#.... +.......................#.........................#.......................................................................................... +.........................................................#...........#.........................#........#..........#.............#.......... +............................#..............#....................#........................................................#.................. +.......#.................................................................#................#................................................. +.................#..................................................................................#........................#...........#.. +...................................................#.......#................................................................................ +.........................................#......................................#......................................#.................... +....................................#...........................................................................#........................... +..............................#.............................................................#...........#.......................#......#.... +.........#...............................................#..............#................................................................... +........................#....................#.....................................#........................................................ +#........................................................................................................................................... +............................#......................................................................#.......#................................ +......................................#..................................................................................................... +.....#............#.........................................#..........................#..........................................#......... +...........................................#......................#..............................................#.......................... +..............#..............................................................................#............................#.............#... +..#......#...........................................#..............................#..................#.....#.............................. +....................#..........#.....#...............................#...................................................................... +............................................................................................................................................ +.................................................#.......................................................................................... +.............#..........#...............................#...............#.............#..........#.........#........#....................... +............................................#................#.................#............................................................ +....................................#....................................................................................#.............#.... diff --git a/2023/aoc2023/day11/src/funcs.rs b/2023/aoc2023/day11/src/funcs.rs new file mode 100644 index 0000000..c5c7415 --- /dev/null +++ b/2023/aoc2023/day11/src/funcs.rs @@ -0,0 +1,43 @@ +pub fn transpose_grid(contents: Vec) -> Vec { + let thing: Vec> = contents + .iter() + .map(|line| line.chars().collect::>()) + .collect(); + let transposed = transpose(thing); + transposed + .iter() + .map(|inner| inner.into_iter().collect::()) + .collect() +} + +fn transpose(v: Vec>) -> Vec> +where + T: Clone, +{ + assert!(!v.is_empty()); + (0..v[0].len()) + .map(|i| v.iter().map(|inner| inner[i].clone()).collect::>()) + .collect() +} + +pub fn find_galaxies(contents: Vec) -> Vec<(usize, usize)> { + let mut output: Vec<(usize, usize)> = Vec::new(); + for (row, line) in contents.iter().enumerate() { + for (col, char) in line.chars().into_iter().enumerate() { + if char == '#' { + output.push((row, col)); + } + } + } + output +} + +pub fn find_empty_rows(grid: &Vec) -> Vec { + let mut result: Vec = Vec::new(); + for (idx, row) in grid.iter().enumerate() { + if !row.contains('#') { + result.push(idx); + } + } + result +} diff --git a/2023/aoc2023/day11/src/main.rs b/2023/aoc2023/day11/src/main.rs index 0e7d855..08be06c 100644 --- a/2023/aoc2023/day11/src/main.rs +++ b/2023/aoc2023/day11/src/main.rs @@ -1,10 +1,12 @@ #![doc = include_str!("../README.md")] +use std::cmp; use std::time::Instant; +use itertools::Itertools; +use funcs::{find_empty_rows, find_galaxies, transpose_grid}; use lube::{get_file_contents, get_input_file_path}; -mod part1; -mod part2; +mod funcs; fn main() { let inp_file_path: std::path::PathBuf = get_input_file_path(); @@ -13,13 +15,84 @@ fn main() { println!("-------------------- PART 1 --------------------"); let part1start = Instant::now(); - let result = part1::solution(&contents); + let result = solve(&contents, 2); println!(">> {result}"); println!(" [{} μs]", part1start.elapsed().as_micros()); println!("-------------------- PART 2 --------------------"); let part2start = Instant::now(); - let result = part2::solution(&contents); + let result = solve(&contents, 1_000_000); println!(">> {result}"); println!(" [{} μs]", part2start.elapsed().as_micros()); } + +fn solve(contents: &Vec<&str>, expansion: u64) -> u64 { + let grid: Vec = contents.iter().map(|s| s.to_string()).collect(); + let empty_rows = find_empty_rows(&grid); + let transposed = transpose_grid(grid); + let empty_cols = find_empty_rows(&transposed); + let galaxies = find_galaxies(transposed); + + let sum_distances: u64 = galaxies + .iter() + .combinations(2) + .map(|combo| { + let found_cols = empty_cols + .iter() + .filter(|&&c| { + let (x1, x2) = (combo[0].0, combo[1].0); + let lower = cmp::min(x1, x2); + let upper = cmp::max(x1, x2); + (lower..upper).contains(&c) + }) + .count() as u64; + let found_rows = empty_rows + .iter() + .filter(|&&c| { + let (y1, y2) = (combo[0].1, combo[1].1); + let lower = cmp::min(y1, y2); + let upper = cmp::max(y1, y2); + (lower..upper).contains(&c) + }) + .count() as u64; + + let absx = (combo[0].0 as i64 - combo[1].0 as i64).abs() as u64; + let absx = absx + ((expansion - 1) * found_rows); + + let absy = (combo[0].1 as i64 - combo[1].1 as i64).abs() as u64; + let absy = absy + ((expansion - 1) * found_cols); + + absx + absy + }) + .sum(); + + sum_distances +} + +#[cfg(test)] +mod tests { + use super::*; + + fn get_sample_data() -> Vec<&'static str> { + let data = "...#......\n.......#..\n#.........\n..........\n......#...\n.#........\n.........#\n..........\n.......#..\n#...#....."; + data.trim().split("\n").collect() + } + + fn dotest(contents: &Vec<&str>, expansion: u64, expected: u64) { + let result = solve(&contents, expansion); + assert_eq!(result, expected); + } + + #[test] + fn test_part1() { + let data = get_sample_data(); + dotest(&data, 2, 374); + } + + #[test] + fn test_part2() { + let data = get_sample_data(); + dotest(&data, 10, 1030); + dotest(&data, 100, 8410); + } +} diff --git a/2023/aoc2023/day11/src/part1.rs b/2023/aoc2023/day11/src/part1.rs deleted file mode 100644 index edb5f9f..0000000 --- a/2023/aoc2023/day11/src/part1.rs +++ /dev/null @@ -1,23 +0,0 @@ -/// Part 1 solution -pub fn solution(contents: &Vec<&str>) -> &'static str { - println!("Part 1 incomplete!"); - println!("{:?}", contents[0]); - "XYZ" -} - -// #[cfg(test)] -// mod tests { -// use super::*; - -// fn get_sample_data() -> Vec<&'static str> { -// let data = ""; -// data.trim().split("\n").collect() -// } - -// #[test] -// fn test_solution() { -// let result = solution(&get_sample_data()); -// let expected = "XYZ"; -// assert_eq!(result, expected); -// } -// } diff --git a/2023/aoc2023/day11/src/part2.rs b/2023/aoc2023/day11/src/part2.rs deleted file mode 100644 index ca897bc..0000000 --- a/2023/aoc2023/day11/src/part2.rs +++ /dev/null @@ -1,23 +0,0 @@ -/// Part 2 solution -pub fn solution(contents: &Vec<&str>) -> &'static str { - println!("Part 2 incomplete!"); - println!("{:?}", contents[0]); - "XYZ" -} - -// #[cfg(test)] -// mod tests { -// use super::*; - -// fn get_sample_data() -> Vec<&'static str> { -// let data = ""; -// data.trim().split("\n").collect() -// } - -// #[test] -// fn test_solution() { -// let result = solution(&get_sample_data()); -// let expected = "XYZ"; -// assert_eq!(result, expected); -// } -// }