From edfe6fcbbf7d1b91f97285d82ca2ab44e0a03e23 Mon Sep 17 00:00:00 2001 From: Adrian Groh Date: Thu, 12 Dec 2024 10:46:46 +0100 Subject: [PATCH] Add day12 --- day12/Cargo.lock | 126 ++++++++++++++++++++++++++++++++++++++++++++++ day12/Cargo.toml | 8 +++ day12/src/main.rs | 122 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 256 insertions(+) create mode 100644 day12/Cargo.lock create mode 100644 day12/Cargo.toml create mode 100644 day12/src/main.rs diff --git a/day12/Cargo.lock b/day12/Cargo.lock new file mode 100644 index 0000000..b55a784 --- /dev/null +++ b/day12/Cargo.lock @@ -0,0 +1,126 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "day12" +version = "0.1.0" +dependencies = [ + "ahash", + "glam", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "glam" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677" + +[[package]] +name = "libc" +version = "0.2.168" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/day12/Cargo.toml b/day12/Cargo.toml new file mode 100644 index 0000000..604011d --- /dev/null +++ b/day12/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day12" +version = "0.1.0" +edition = "2021" + +[dependencies] +ahash = "0.8.11" +glam = "0.29.2" diff --git a/day12/src/main.rs b/day12/src/main.rs new file mode 100644 index 0000000..0cc65c3 --- /dev/null +++ b/day12/src/main.rs @@ -0,0 +1,122 @@ +use ahash::AHashSet; +use glam::IVec2; + +fn parse(input: &str) -> Vec> { + input.lines().map(|l| l.chars().collect()).collect() +} + +const DIRECTIONS: [IVec2; 4] = [ + IVec2 { x: -1, y: 0 }, + IVec2 { x: 1, y: 0 }, + IVec2 { x: 0, y: -1 }, + IVec2 { x: 0, y: 1 }, +]; + +fn get_region(pos: &IVec2, map: &[Vec]) -> AHashSet { + let mut res = AHashSet::new(); + let mut prev_amount = 0; + let plot_type = map[pos.x as usize][pos.y as usize]; + res.insert(*pos); + while res.len() != prev_amount { + let mut new_plots = AHashSet::new(); + for plot in &res { + for direction in DIRECTIONS { + let new_pos = plot + direction; + if let Some(Some(new_plot)) = map + .get(new_pos.x as usize) + .map(|v| v.get(new_pos.y as usize)) + { + if new_plot == &plot_type { + new_plots.insert(new_pos); + } + } + } + } + prev_amount = res.len(); + res.extend(new_plots); + } + res +} + +fn get_perimeter(region: &AHashSet) -> usize { + let mut res = 0; + for pos in region { + for direction in DIRECTIONS { + if !region.contains(&(pos + direction)) { + res += 1; + } + } + } + res +} + +fn get_connected(pos: &IVec2, all_pos: &AHashSet) -> AHashSet { + let mut res = AHashSet::new(); + res.insert(*pos); + let mut last_len = 0; + while last_len != res.len() { + let mut new_positions = AHashSet::new(); + for checking in &res { + for direction in DIRECTIONS { + if all_pos.contains(&(checking + direction)) { + new_positions.insert(checking + direction); + } + } + } + last_len = res.len(); + res.extend(new_positions); + } + res +} + +fn get_sides(region: &AHashSet) -> usize { + let mut res = 0; + for direction in DIRECTIONS { + let mut outside = AHashSet::new(); + for plot in region { + if !region.contains(&(plot + direction)) { + outside.insert(plot + direction); + } + } + while !outside.is_empty() { + let connected = get_connected(outside.iter().next().unwrap(), &outside); + res += 1; + outside.retain(|p| !connected.contains(p)); + } + } + res +} + +fn part12(map: &[Vec], part2: bool) -> usize { + let mut positions: AHashSet = (0..map.len()) + .flat_map(|x| { + (0..map[0].len()).map(move |y| IVec2 { + x: x as i32, + y: y as i32, + }) + }) + .collect(); + let mut regions = vec![]; + while !positions.is_empty() { + let region = get_region(positions.iter().next().unwrap(), map); + positions.retain(|p| !region.contains(p)); + regions.push(region); + } + regions + .iter() + .map(|r| { + r.len() + * if part2 { + get_sides(r) + } else { + get_perimeter(r) + } + }) + .sum() +} + +fn main() { + let input = parse(include_str!("../input.txt")); + println!("{}", part12(&input, false)); + println!("{}", part12(&input, true)); +}