From 61a5cd899ec3386f6ebf71304ff5dbbbc1f54d5c Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Thu, 12 Dec 2024 12:07:17 -0600 Subject: [PATCH] Day 12 part 1 with a little work on part 2 --- 2024/rust/src/day12.rs | 125 ++++++++++++++++++++++++++++++++++++++ 2024/rust/src/template.rs | 4 +- 2 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 2024/rust/src/day12.rs diff --git a/2024/rust/src/day12.rs b/2024/rust/src/day12.rs new file mode 100644 index 0000000..bde4bb5 --- /dev/null +++ b/2024/rust/src/day12.rs @@ -0,0 +1,125 @@ +mod prelude; +pub use crate::prelude::*; + +fn main() { + let input = day_input(12); + show_answers(part1(&input), part2(&input)); +} + +#[derive(Debug, Hash, PartialEq, Eq)] +enum Dir { + N, + S, + E, + W, +} + +#[derive(Debug)] +struct Region { + locations: HashSet<(usize, usize)>, + perimeters: HashSet<(usize, usize, Dir)>, +} + +impl Region { + fn measure_at(bytes: &Vec>, sx: usize, sy: usize) -> Self { + let target = bytes[sy][sx]; + let (height, width) = (bytes.len(), bytes[0].len()); + let mut candidates = vec![(sx, sy)]; + let mut locations = HashSet::from_iter(candidates.clone()); + let mut perimeters = HashSet::new(); + + while let Some((x, y)) = candidates.pop() { + print!("AT {x},{y}: "); + for (nx, ny, d) in [ + (x, y.saturating_sub(1), Dir::N), + (x, y + 1, Dir::S), + (x + 1, y, Dir::E), + (x.saturating_sub(1), y, Dir::W), + ] { + if (nx, ny) == (x, y) || nx >= width || ny >= height { + print!("EDGE@{nx},{ny}; "); + perimeters.insert((nx, ny, d)); + continue; + } + if bytes[ny][nx] != target { + print!("EDGE@{nx},{ny}; "); + perimeters.insert((nx, ny, d)); + continue; + } + if !locations.contains(&(nx, ny)) { + candidates.push((nx, ny)); + locations.insert((nx, ny)); + } + } + print!("\n"); + } + Self { + locations, + perimeters, + } + } +} + +fn part1(input: &str) -> usize { + let mut regions = vec![]; + let bytes: Vec> = input + .trim() + .lines() + .map(|l| l.trim().bytes().collect()) + .collect(); + let mut regionated: HashSet<(usize, usize)> = HashSet::new(); + for y in 0..bytes.len() { + for x in 0..bytes[y].len() { + if regionated.contains(&(x, y)) { + continue; + } + let region = Region::measure_at(&bytes, x, y); + println!( + "New Region: (Byte: {}, Area: {}, Perimeter: {})", + bytes[y][x], + ®ion.locations.len(), + ®ion.perimeters.len(), + ); + regionated.extend(®ion.locations); + regions.push(region); + } + } + println!("{regions:?}"); + regions + .iter() + .map(|r| r.locations.len() * r.perimeters.len()) + .sum() +} + +fn part2(input: &str) -> usize { + 0 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let input = r#"RRRRIICCFF +RRRRIICCCF +VVRRRCCFFF +VVRCCCJFFF +VVVVCJJCFE +VVIVCCJJEE +VVIIICJJEE +MIIIIIJJEE +MIIISIJEEE +MMMISSJEEE"#; + let bytes: Vec> = input + .trim() + .lines() + .map(|l| l.trim().bytes().collect()) + .collect(); + let region = Region::measure_at(&bytes, 0, 0); + assert_eq!(region.locations.len(), 12); + assert_eq!(region.perimeters.len(), 18); + assert_eq!(part1(input), 1930); + assert_eq!(part2(input), 1206); + } +} diff --git a/2024/rust/src/template.rs b/2024/rust/src/template.rs index 2505311..f7fb147 100644 --- a/2024/rust/src/template.rs +++ b/2024/rust/src/template.rs @@ -6,11 +6,11 @@ fn main() { show_answers(part1(&input), part2(&input)); } -fn part1(input: &str) -> i64 { +fn part1(input: &str) -> usize { 0 } -fn part2(input: &str) -> i64 { +fn part2(input: &str) -> usize { 0 }