diff --git a/Cargo.lock b/Cargo.lock index 60eb36c..52ef9a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,6 +22,7 @@ name = "advent" version = "0.1.0" dependencies = [ "getrandom", + "itertools", "num-bigint", "num-irrational", "num-rational", @@ -318,6 +319,12 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "encoding_rs" version = "0.8.33" @@ -613,6 +620,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.9" diff --git a/lib/Cargo.toml b/lib/Cargo.toml index a288dfb..fc13201 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -10,7 +10,8 @@ num-rational = { version = "0.4.1", features = ["num-bigint"] } regex = "1.10.2" scraper = "0.18.1" reqwest = "0.11.22" +itertools = "0.12.0" [dependencies.getrandom] version = "0.2.11" -features = ["js"] \ No newline at end of file +features = ["js"] diff --git a/lib/src/day11/mod.rs b/lib/src/day11/mod.rs new file mode 100644 index 0000000..8c30e86 --- /dev/null +++ b/lib/src/day11/mod.rs @@ -0,0 +1,115 @@ +use crate::utils::Day; +use itertools::Itertools as _; + +#[derive(Debug, Default)] +pub struct Day11 { + pub input: String, + pub rows_expanded: Vec, + pub columns_expanded: Vec, +} + +impl Day for Day11 { + fn part1(&mut self) -> String { + let mut parsed: Vec> = self + .input + .lines() + .map(|line| line.chars().collect()) + .collect(); + + for line in std::mem::take(&mut parsed).into_iter() { + if line.iter().all(|&c| c == '.') { + parsed.push(line.clone()) + } + parsed.push(line) + } + + let parsed_clone = parsed.clone(); + let mut added = 0usize; + for column in 0..parsed[0].len() { + if (0..parsed.len()).all(|row| parsed_clone[row][column] == '.') { + parsed + .iter_mut() + .for_each(|line| line.insert(column + added, '.')); + added += 1; + } + } + + let galaxies: Vec<_> = parsed + .iter() + .enumerate() + .flat_map(|(i, line)| { + line.iter() + .enumerate() + .filter_map(move |(j, &c)| if c == '#' { Some((i as isize, j as isize)) } else { None }) + }) + .collect(); + + let combinations = galaxies + .into_iter() + .combinations(2) + .map(|c| (c[0], c[1])) + .collect::>(); + + let result = combinations.into_iter().map( + |(start, end)| + (end.0 - start.0).abs() + (end.1 - start.1).abs() + ).sum::(); + + result.to_string() + } + + fn part2(&mut self) -> String { + let parsed: Vec> = self + .input + .lines() + .map(|line| line.chars().collect()) + .collect(); + + for (i, line) in parsed.iter().enumerate() { + if line.iter().all(|&c| c == '.') { + self.rows_expanded.push(i); + } + } + + let parsed_clone = parsed.clone(); + for column in 0..parsed[0].len() { + if (0..parsed.len()).all(|row| parsed_clone[row][column] == '.') { + self.columns_expanded.push(column); + } + } + + let galaxies: Vec<_> = parsed + .iter() + .enumerate() + .flat_map(|(i, line)| { + line.iter() + .enumerate() + .filter_map({ + let rows_expanded = &self.rows_expanded; + let columns_expanded = &self.columns_expanded; + move |(j, &c)| { + if c == '#' { + Some(( + i as i128 + (rows_expanded.iter().filter(|&&row| row < i).count() as i128 * 999999i128), + j as i128 + (columns_expanded.iter().filter(|&&column| column < j).count() as i128 * 999999i128) + )) + } else { None } + } + }) + }) + .collect(); + + let combinations = galaxies + .into_iter() + .combinations(2) + .map(|c| (c[0], c[1])) + .collect::>(); + + let result = combinations.into_iter().map( + |(start, end)| + (end.0 - start.0).abs() + (end.1 - start.1).abs() + ).sum::(); + + result.to_string() + } +} diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 2890a06..a7d6fe7 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use day1::Day1; use day10::Day10; +use day11::Day11; use day2::Day2; use day3::Day3; use day4::Day4; @@ -17,6 +18,7 @@ pub mod utils; pub mod day1; pub mod day10; +pub mod day11; pub mod day2; pub mod day3; pub mod day4; @@ -51,6 +53,7 @@ pub fn get_day(day: u8, input: String) -> Box { input, parsed: vec![], }), + 11 => Box::new(Day11 { input, rows_expanded: vec![], columns_expanded: vec![] }), _ => panic!("Invalid day #"), } -} \ No newline at end of file +} diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index 8cb9b2d..85a2e7b 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -3,4 +3,4 @@ use wasm_bindgen::prelude::*; #[wasm_bindgen] pub async fn solve(day: u8, part: u8, auth: String) -> String { advent::get_day(day, advent::fetcher::fetch_input(auth, day).await).solve(part, false) -} \ No newline at end of file +}