From c2d7a4beec947540ac205fbadc767b90b4874d4b Mon Sep 17 00:00:00 2001 From: Tyler Beckman Date: Thu, 12 Dec 2024 23:24:19 -0700 Subject: [PATCH] Day 12 p2 progress??? i have no fucking clue how to solve this --- Cargo.toml | 4 ++ day12/part2.rs | 140 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 day12/part2.rs diff --git a/Cargo.toml b/Cargo.toml index 67f5862..0eae11b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,7 @@ path = "day11/part2.rs" [[bin]] name = "d12p1" path = "day12/part1.rs" + +[[bin]] +name = "d12p2" +path = "day12/part2.rs" diff --git a/day12/part2.rs b/day12/part2.rs new file mode 100644 index 0000000..1e81e7d --- /dev/null +++ b/day12/part2.rs @@ -0,0 +1,140 @@ +#![feature(let_chains)] +use std::collections::{HashSet, VecDeque}; + +const GRID_SIZE: usize = include_bytes!("input.txt").len().isqrt(); + +fn dfs(grid: &[[char; GRID_SIZE]; GRID_SIZE], start: (usize, usize)) -> HashSet<(usize, usize)> { + let mut queue = VecDeque::from([start]); + let mut set = HashSet::from([start]); + let plant_type = grid[start.0][start.1]; + + while let Some(next) = queue.pop_front() { + let to_check = [ + (next.0 + 1, next.1), + (next.0.wrapping_sub(1), next.1), + (next.0, next.1 + 1), + (next.0, next.1.wrapping_sub(1)), + ]; + for pos in to_check { + if set.contains(&pos) { + continue; + } + + if let Some(plant) = grid.get(pos.0).and_then(|r| r.get(pos.1)) + && *plant == plant_type + { + queue.push_back(pos); + set.insert(pos); + } + } + } + + set +} + +// fn dfs_perimeter( +// perimeter_set: &HashSet<(isize, isize)>, +// start: (isize, isize), +// ) -> HashSet<(isize, isize)> { +// let mut queue = VecDeque::from([start]); +// let mut set = HashSet::from([start]); + +// while let Some(next) = queue.pop_front() { +// let to_check = [ +// (next.0 + 1, next.1), +// (next.0 - 1, next.1), +// (next.0, next.1 + 1), +// (next.0, next.1 - 1), +// ]; +// for pos in to_check { +// if set.contains(&pos) { +// continue; +// } + +// if perimeter_set.contains(&pos) { +// queue.push_back(pos); +// set.insert(pos); +// } +// } +// } + +// set +// } + +fn main() { + let mut input_iter = include_str!("input.txt").lines().map(|l| { + let mut iter = l.chars(); + std::array::from_fn::<_, GRID_SIZE, _>(|_| iter.next().unwrap()) + }); + let grid: [_; GRID_SIZE] = std::array::from_fn(|_| input_iter.next().unwrap()); + + // Parse all independent regions + let mut regions = Vec::<(char, HashSet<(usize, usize)>)>::new(); + for row in 0..GRID_SIZE { + for col in 0..GRID_SIZE { + if regions.iter().all(|region| !region.1.contains(&(row, col))) { + regions.push((grid[row][col], dfs(&grid, (row, col)))); + } + } + } + + // Sanity check -> are there any duplicated nodes between the regions? + assert_eq!( + regions.iter().map(|r| r.1.len()).sum::(), + regions + .iter() + .map(|r| &r.1) + .flatten() + .collect::>() + .len() + ); + + // Expand grid by two because im going insane + let mut expanded_grid = [[' '; GRID_SIZE * 2 + 1]; GRID_SIZE * 2 + 1]; + for row in 0..GRID_SIZE { + for col in 0..GRID_SIZE { + expanded_grid[row * 2 + 1][col * 2 + 1] = grid[row][col]; + } + } + + for row in 0..(GRID_SIZE*2+1) { + print!("|"); + for col in 0..(GRID_SIZE*2+1) { + print!("{}", expanded_grid[row][col]); + } + println!("|"); + } + + + // Calculate area and sides of each + let mut sum = 0; + for (plant_type, region) in regions.into_iter() { + let area = region.len(); + let sides = 0; + + // Clone the expanded grid + let expanded_grid_clone = expanded_grid.clone(); + for pos in region.iter() { + // None in a position is a special case meaning "overfilled in the negative direction" + // Since we don't actually access the point there, it just gets treated like -1 would + let to_check = [ + (pos.0.checked_add(1), Some(pos.1)), + (pos.0.checked_sub(1), Some(pos.1)), + (Some(pos.0), pos.1.checked_add(1)), + (Some(pos.0), pos.1.checked_sub(1)), + ]; + for outer_pos in to_check { + if (outer_pos.0.is_none() || outer_pos.1.is_none()) + || !region.contains(&(outer_pos.0.unwrap(), outer_pos.1.unwrap())) + { + expanded_grid_clone[outer_pos.0.map(|p| p * 2 + 1)] + } + } + } + + sum += area * sides; + println!("{plant_type}: {area}A {sides}S"); + } + + println!("Result: {sum}"); +}