diff --git a/Cargo.lock b/Cargo.lock index 06c327d..7219f43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,7 @@ dependencies = [ name = "aoc2023" version = "0.1.0" dependencies = [ + "itertools", "regex", "shared", "substring", @@ -34,6 +35,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + [[package]] name = "memchr" version = "2.6.4" diff --git a/aoc2023/Cargo.toml b/aoc2023/Cargo.toml index 0b76455..81acc05 100644 --- a/aoc2023/Cargo.toml +++ b/aoc2023/Cargo.toml @@ -6,4 +6,5 @@ edition = "2021" [dependencies] shared = { path = "../shared" } regex = "1.10.2" -substring = "1.4.5" \ No newline at end of file +substring = "1.4.5" +itertools = "0.12.0" \ No newline at end of file diff --git a/aoc2023/src/day11.rs b/aoc2023/src/day11.rs index 2e4945b..ae38301 100644 --- a/aoc2023/src/day11.rs +++ b/aoc2023/src/day11.rs @@ -1,13 +1,55 @@ use shared::{Solution, Answer}; +use itertools::Itertools; pub struct Day11; impl Solution for Day11 { fn part_1(&self, input: &str) -> Answer { - Answer::Unimplemented + Answer::from(solve(input, 2)) } fn part_2(&self, input: &str) -> Answer { - Answer::Unimplemented + Answer::from(solve(input, 1_000_000)) } } + +fn solve(input: &str, inflation_arg: usize) -> u64 { + let grid = input.lines().map(|line| line.chars().map(|x| x == '#').collect::>()).collect::>(); + + let mut distances = vec![vec![1; grid[0].len()]; grid.len()]; + + let mut empty_col = vec![true; grid[0].len()]; + for (i, line) in grid.iter().enumerate() { + empty_col = empty_col.iter().enumerate().map(|(i, &l)| l && !line[i]).collect(); + if !line.iter().any(|&x| x) { + distances[i] = vec![inflation_arg; line.len()]; + } + } + + for (i, &col) in empty_col.iter().enumerate() { + if col { + for j in 0..distances.len() { + distances[j][i] = inflation_arg; + } + } + } + + let galaxies: Vec<(usize, usize)> = grid.iter(). + enumerate(). + map(|(i, line)| line.iter() + .enumerate() + .filter_map(|(j, &x)| if x { Some((i, j)) } else { None }) + .collect::>() + ).flatten().collect::>(); + + galaxies.iter().permutations(2).map(|x| { + let (x1, y1): (usize, usize) = *x[0]; + let (x2, y2): (usize, usize) = *x[1]; + let mut out = 0; + let xrange = x1.min(x2)..x1.max(x2); + let yrange = if y1 <= y2 { y1..y2 } else { (y2+1)..(y1+1) }; + for i in xrange { out += distances[i][if x1 <= x2 {y1} else {y2}] } + for j in yrange { out += distances[x1.min(x2)][j] } + out as u64 + } ).sum::() / 2 +} diff --git a/src/main.rs b/src/main.rs index 8ac0506..cacd3a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,10 +8,10 @@ use std::time::Instant; fn main() { let now = Instant::now(); - let Ok(data) = load_actual(2023, 10) + let Ok(data) = load_actual(2023, 11) else { panic!("No Input Data"); }; - let result = aoc2023::day10::Day10.part_2(&data); + let result = aoc2023::day11::Day11.part_2(&data); let elapsed = now.elapsed();