From 9af86b1970dfbd9dfbca1b627d42c4cfbd818f3f Mon Sep 17 00:00:00 2001 From: Erin Date: Mon, 4 Dec 2023 20:50:43 +0100 Subject: [PATCH] Day 3 Part 2 --- src/bin/day03.rs | 111 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 35 deletions(-) diff --git a/src/bin/day03.rs b/src/bin/day03.rs index e8b7785..e3dfb05 100644 --- a/src/bin/day03.rs +++ b/src/bin/day03.rs @@ -2,41 +2,80 @@ use color_eyre::{ eyre::{bail, ensure}, Result, }; -use std::io::stdin; +use std::{cell::Cell, collections::HashMap, io::stdin, rc::Rc}; -fn part1( - matrix: &[u8], +#[derive(Clone, Copy)] +struct SliceCols<'a, T> { cols: usize, -) -> Result> + '_> { - let cols_sig = isize::try_from(cols)?; - - Ok(matrix - .chunks(cols) - .flat_map(|chunk| chunk.split(|pred| !(*pred as char).is_ascii_digit())) - .filter(|s| !s.is_empty()) - .map(move |slice| { - let ix = slice.as_ptr() as usize - matrix.as_ptr() as usize; - (ix..slice.len() + ix) - .flat_map(|ix| { - (ix % cols != 0) - .then_some([-1, cols_sig - 1, -cols_sig - 1]) - .into_iter() - .chain((ix % cols != cols - 1).then_some([1, cols_sig + 1, -cols_sig + 1])) - .flatten() - .chain([-cols_sig, cols_sig]) - .flat_map(move |offset| ix.checked_add_signed(offset)) - }) - .flat_map(|ix| matrix.get(ix)) - .any(|&b| (b as char).is_ascii_punctuation() && b != b'.') - .then(|| String::from_utf8_lossy(slice).parse::()) - .transpose() - .map(|x| x.unwrap_or_default()) - })) + data: &'a [T], } -fn part2(matrix: &[u8], cols: usize) -> Result> + '_> { - - Ok(std::iter::once(Ok(0))) +fn separate_numbers(matrix: SliceCols) -> impl Iterator { + matrix + .data + .chunks(matrix.cols) + .flat_map(|chunk| chunk.split(|&b| !char::from(b).is_ascii_digit())) + .filter(|s| !s.is_empty()) +} + +fn around_indices(ix: usize, cols: usize) -> impl Iterator { + let cols_sig = isize::try_from(cols).expect("Length can't be larger than isize::MAX"); + (ix % cols != 0) + .then_some([-1, cols_sig - 1, -cols_sig - 1]) + .into_iter() + .chain((ix % cols != cols - 1).then_some([1, cols_sig + 1, -cols_sig + 1])) + .flatten() + .chain([-cols_sig, cols_sig]) + .flat_map(move |offset| ix.checked_add_signed(offset)) +} + +fn part1(matrix: SliceCols) -> u64 { + separate_numbers(matrix) + .map(move |slice| { + let ix = slice.as_ptr() as usize - matrix.data.as_ptr() as usize; + (ix..slice.len() + ix) + .flat_map(|ix| around_indices(ix, matrix.cols)) + .flat_map(|ix| matrix.data.get(ix)) + .any(|&b| (b as char).is_ascii_punctuation() && b != b'.') + .then(|| { + String::from_utf8_lossy(slice) + .parse::() + .expect("Filter already isolated numbers") + }) + .unwrap_or_default() + }) + .sum() +} + +fn part2(matrix: SliceCols) -> u64 { + let numbers: HashMap>>> = separate_numbers(matrix) + .flat_map(|slice| { + let num = Rc::new(Cell::new(Some( + String::from_utf8_lossy(slice) + .parse::() + .expect("Filter already isolated numbers"), + ))); + slice + .iter() + .map(|i| i as *const u8 as usize - matrix.data.as_ptr() as usize) + .zip(std::iter::repeat(num)) + }) + .collect(); + + matrix + .data + .iter() + .filter(|&&b| b == b'*') + .map(|i| i as *const u8 as usize - matrix.data.as_ptr() as usize) + .map(|ix| { + let mut it = around_indices(ix, matrix.cols).flat_map(|ix| { + let i = numbers.get(&ix)?; + i.take() + }); + + it.next().unwrap_or_default() * it.next().unwrap_or_default() * it.product::() + }) + .sum() } fn main() -> Result<()> { @@ -60,10 +99,12 @@ fn main() -> Result<()> { Ok(()) })?; - println!( - "{}", - part1(&matrix, cols)?.try_fold::<_, _, Result<_>>(0, |acc, x| Ok(acc + x?))? - ); + let matrix = SliceCols { + cols, + data: &matrix, + }; + + println!("{}", part2(matrix)); Ok(()) }