From d3430aa43278d7219acc5a6b84cf3e3f1eeb35c3 Mon Sep 17 00:00:00 2001 From: Tobias Berger Date: Sun, 3 Dec 2023 11:25:49 +0100 Subject: [PATCH] Rust Day 3 Part 2 --- rust/Cargo.lock | 2 +- rust/Cargo.toml | 2 +- rust/src/day03/part_2.rs | 78 ++++++++++++++++++++++++++++++++++------ 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 7fa7307..60d92cf 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -4,4 +4,4 @@ version = 3 [[package]] name = "advent-of-code" -version = "23.3.1" +version = "23.3.2" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index cb7b221..27a56d8 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "advent-of-code" -version = "23.3.1" +version = "23.3.2" edition = "2021" default-run = "day03" diff --git a/rust/src/day03/part_2.rs b/rust/src/day03/part_2.rs index 928ee24..ef2a914 100644 --- a/rust/src/day03/part_2.rs +++ b/rust/src/day03/part_2.rs @@ -1,5 +1,69 @@ -pub(crate) fn part_2(_input: &'static str) -> u64 { - todo!("Part 2") +use std::collections::HashMap; + +#[derive(Debug)] +struct PartNumber { + number: u64, + adjacent_gear: usize, +} + +pub(crate) fn part_2(input: &'static str) -> u64 { + let mut part_numbers = vec![]; + for (y, line) in input.lines().enumerate() { + let mut search_index = 0; + loop { + let search_line = &line[search_index..]; + if search_line.is_empty() { + break; + } + let Some(number_start) = search_line.find(|c| char::is_ascii_digit(&c)) else { + break; + }; + let number_end = search_line[number_start..] + .find(|c| !char::is_ascii_digit(&c)) + .unwrap_or(search_line.len() - number_start) + + number_start; + + let number = search_line[number_start..number_end] + .parse() + .expect("Should be a valid number"); + + let mut gears = vec![]; + // This `line.len()` assumes the input is square + for y in y.saturating_sub(1)..=usize::min(y + 1, line.len() - 1) { + for x in (search_index + number_start).saturating_sub(1) + ..=usize::min(search_index + number_end, line.len()) + { + let idx = y * (line.len() + 1) + x; + let char = input.as_bytes()[idx] as char; + if matches!(char, '*') { + gears.push(idx) + } + } + } + + part_numbers.extend(gears.iter().map(|&gear| PartNumber { + number, + adjacent_gear: gear, + })); + search_index += number_end; + } + } + + let mut groups = HashMap::new(); + + for part_number in part_numbers { + let Some(group) = groups.get_mut(&part_number.adjacent_gear) else { + groups.insert(part_number.adjacent_gear, vec![part_number]); + continue; + }; + group.push(part_number); + } + + groups + .values() + .filter(|group| group.len() == 2) + .map(|group| group[0].number * group[1].number) + .sum() } #[cfg(test)] @@ -8,17 +72,11 @@ mod tests { #[test] fn test_with_sample_solution() { - assert_eq!( - super::part_2(SAMPLE_INPUT), - todo!("Add result from example part 2") - ); + assert_eq!(super::part_2(SAMPLE_INPUT), 467835); } #[test] fn test_with_solution() { - assert_eq!( - super::part_2(crate::INPUT), - todo!("Add result for solved part 2") - ); + assert_eq!(super::part_2(crate::INPUT), 80703636); } }