From 8cd421a8efb7340f59f7fa454983d9b7b9989ee6 Mon Sep 17 00:00:00 2001 From: Jan-Bulthuis Date: Thu, 12 Dec 2024 06:36:59 +0100 Subject: [PATCH] day11-12 --- aoc_2024/src/day11.rs | 5 +- aoc_2024/src/day12.rs | 174 ++++++++++++++++++++++++++++++++++++++++++ aoc_2024/src/lib.rs | 1 + 3 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 aoc_2024/src/day12.rs diff --git a/aoc_2024/src/day11.rs b/aoc_2024/src/day11.rs index b629a23..fcd4e3c 100644 --- a/aoc_2024/src/day11.rs +++ b/aoc_2024/src/day11.rs @@ -1,13 +1,10 @@ -use std::collections::VecDeque; - use aoc_runner_derive::{aoc, aoc_generator}; -use hashbrown::{hash_map::Entry, HashMap}; +use hashbrown::HashMap; use nom::{ character::complete::{space1, u64 as parse_usize}, error::Error, multi::separated_list1, }; -use rayon::prelude::*; type Input = Vec; diff --git a/aoc_2024/src/day12.rs b/aoc_2024/src/day12.rs new file mode 100644 index 0000000..5876ca8 --- /dev/null +++ b/aoc_2024/src/day12.rs @@ -0,0 +1,174 @@ +use aoc_runner_derive::{aoc, aoc_generator}; + +type Input = Vec>; + +#[aoc_generator(day12)] +fn parse(input: &str) -> Input { + input.lines().map(|line| line.chars().collect()).collect() +} + +#[aoc(day12, part1)] +fn part1(input: &Input) -> usize { + let w = input[0].len(); + let h = input.len(); + + let mut region_idx = -1; + let mut region_border_size = vec![]; + let mut region_size = vec![]; + let mut region = vec![vec![-1; w]; h]; + + for y in 0..h { + for x in 0..w { + let val = input[y][x]; + if region[y][x] == -1 { + region_idx += 1; + let mut queue = vec![(x, y)]; + let mut size = 0; + let mut border_size = 0; + + while let Some((x, y)) = queue.pop() { + if region[y][x] != -1 { + continue; + } + + region[y][x] = region_idx; + size += 1; + + let mut sides = 4; + + if x > 0 && input[y][x - 1] == val { + queue.push((x - 1, y)); + sides -= 1; + } + if x < w - 1 && input[y][x + 1] == val { + queue.push((x + 1, y)); + sides -= 1; + } + if y > 0 && input[y - 1][x] == val { + queue.push((x, y - 1)); + sides -= 1; + } + if y < h - 1 && input[y + 1][x] == val { + queue.push((x, y + 1)); + sides -= 1; + } + + border_size += sides; + } + + region_size.push(size); + region_border_size.push(border_size); + } + } + } + + region_size + .iter() + .zip(region_border_size.iter()) + .map(|(a, b)| *a * *b) + .sum() +} + +#[aoc(day12, part2)] +fn part2(input: &Input) -> usize { + let w = input[0].len(); + let h = input.len(); + + let mut region_idx = -1; + let mut region_border_size = vec![]; + let mut region_size = vec![]; + let mut region = vec![vec![-1; w]; h]; + + for y in 0..h { + for x in 0..w { + let val = input[y][x]; + if region[y][x] == -1 { + region_idx += 1; + let mut queue = vec![(x, y)]; + let mut size = 0; + let mut border_size = 0; + + while let Some((x, y)) = queue.pop() { + if region[y][x] != -1 { + continue; + } + + region[y][x] = region_idx; + size += 1; + + let mut up = false; + let mut down = false; + let mut left = false; + let mut right = false; + let mut up_right = false; + let mut down_left = false; + + if x > 0 && input[y][x - 1] == val { + queue.push((x - 1, y)); + left = true; + } + if x < w - 1 && input[y][x + 1] == val { + queue.push((x + 1, y)); + right = true; + } + if y > 0 && input[y - 1][x] == val { + queue.push((x, y - 1)); + up = true; + } + if y < h - 1 && input[y + 1][x] == val { + queue.push((x, y + 1)); + down = true; + } + if y > 0 && x < w - 1 && input[y - 1][x + 1] == val { + up_right = true; + } + if y < h - 1 && x > 0 && input[y + 1][x - 1] == val { + down_left = true; + } + + if !up && !left { + border_size += 2; + } + if !down && !right { + border_size += 2; + } + if up && right && !up_right { + border_size += 2; + } + if down && left && !down_left { + border_size += 2; + } + } + + region_size.push(size); + region_border_size.push(border_size); + } + } + } + + region_size + .iter() + .zip(region_border_size.iter()) + .map(|(a, b)| *a * *b) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example() { + assert_eq!(part1(&parse("AAAA\nBBCD\nBBCC\nEEEC")), 140); + assert_eq!(part1(&parse("OOOOO\nOXOXO\nOOOOO\nOXOXO\nOOOOO")), 772); + assert_eq!(part1(&parse("RRRRIICCFF\nRRRRIICCCF\nVVRRRCCFFF\nVVRCCCJFFF\nVVVVCJJCFE\nVVIVCCJJEE\nVVIIICJJEE\nMIIIIIJJEE\nMIIISIJEEE\nMMMISSJEEE")), 1930); + } + + #[test] + fn part2_example() { + assert_eq!(part2(&parse("AAAA\nBBCD\nBBCC\nEEEC")), 80); + assert_eq!(part2(&parse("OOO\nOXO\nOOO")), 68); + assert_eq!(part2(&parse("OOOOO\nOXXXX\nOOOOO\nOXXXX\nOOOOO")), 236); + assert_eq!(part2(&parse("RRRRIICCFF\nRRRRIICCCF\nVVRRRCCFFF\nVVRCCCJFFF\nVVVVCJJCFE\nVVIVCCJJEE\nVVIIICJJEE\nMIIIIIJJEE\nMIIISIJEEE\nMMMISSJEEE")), 1206); + } +} diff --git a/aoc_2024/src/lib.rs b/aoc_2024/src/lib.rs index adc4a0d..818035b 100644 --- a/aoc_2024/src/lib.rs +++ b/aoc_2024/src/lib.rs @@ -1,6 +1,7 @@ mod day1; mod day10; mod day11; +mod day12; mod day2; mod day3; mod day4;