From 45b6f64a3ee80d1872b05ec48ad7fdf16a79cf65 Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Sun, 3 Dec 2023 13:13:03 +0100 Subject: [PATCH] day(03): refactor the solution Signed-off-by: Matej Focko --- src/bin/day03.rs | 150 +++++++++++++++++++++-------------------------- 1 file changed, 67 insertions(+), 83 deletions(-) diff --git a/src/bin/day03.rs b/src/bin/day03.rs index e972612..52de8e9 100644 --- a/src/bin/day03.rs +++ b/src/bin/day03.rs @@ -5,19 +5,33 @@ use aoc_2023::*; type Output1 = i32; type Output2 = Output1; +struct Number { + y: usize, + x_min: usize, + x_max: usize, + value: i32, +} + +impl Number { + fn new(y: usize, x_min: usize, x_max: usize, value: i32) -> Number { + Number { + y, + x_min, + x_max, + value, + } + } +} + struct Day03 { - lines: Vec, + symbols: HashMap<(usize, usize), char>, + numbers: Vec, } impl Solution for Day03 { fn new>(pathname: P) -> Self { - Self { - lines: file_to_lines(pathname), - } - } + let lines = file_to_lines(pathname); - fn part_1(&mut self) -> Output1 { - let symbols = self - .lines + let symbols = lines .iter() .enumerate() .flat_map(|(y, line)| { @@ -30,72 +44,8 @@ impl Solution for Day03 { }) }) .collect::>(); - let numbers = self - .lines - .iter() - .enumerate() - .flat_map(|(y, line)| { - let mut nums = vec![]; - let mut start = line.len(); - let mut num = 0; - for (x, c) in line.chars().enumerate() { - if c.is_ascii_digit() { - start = cmp::min(start, x); - num = num * 10 + c.to_digit(10).unwrap() as i32; - } else { - nums.push((y + 1, start + 1, x + 1, num)); - - start = line.len(); - num = 0; - } - } - - if start != line.len() { - nums.push((y + 1, start + 1, line.len() + 1, num)); - } - - nums - }) - .collect_vec(); - - numbers - .iter() - .filter_map(|(y, start, x, num)| { - if symbols.contains_key(&(*y, start - 1)) - || symbols.contains_key(&(*y, *x)) - || (*start - 1..=*x).any(|xx| { - symbols.contains_key(&(y - 1, xx)) || symbols.contains_key(&(y + 1, xx)) - }) - { - Some(*num) - } else { - None - } - }) - .sum() - } - - fn part_2(&mut self) -> Output2 { - let symbols = self - .lines - .iter() - .enumerate() - .flat_map(|(y, line)| { - line.chars().enumerate().filter_map(move |(x, c)| { - if c == '*' { - Some(((y + 1, x + 1), c)) - } else { - None - } - }) - }) - .collect::>(); - - let mut symbol_counters: HashMap<(usize, usize), Vec> = HashMap::new(); - - let numbers = self - .lines + let numbers = lines .iter() .enumerate() .flat_map(|(y, line)| { @@ -108,7 +58,7 @@ impl Solution for Day03 { start = cmp::min(start, x); num = num * 10 + c.to_digit(10).unwrap() as i32; } else if start != line.len() { - nums.push((y + 1, start + 1, x + 1, num)); + nums.push(Number::new(y + 1, start + 1, x + 1, num)); start = line.len(); num = 0; @@ -116,25 +66,59 @@ impl Solution for Day03 { } if start != line.len() { - nums.push((y + 1, start + 1, line.len() + 1, num)); + nums.push(Number::new(y + 1, start + 1, line.len() + 1, num)); } nums }) .collect_vec(); - numbers.iter().for_each(|(y, start, x, num)| { - let mut possible_gears = vec![(*y, start - 1), (*y, *x)]; + Self { symbols, numbers } + } - (*start - 1..=*x).for_each(|xx: usize| { - possible_gears.push((y - 1, xx)); - possible_gears.push((y + 1, xx)); + fn part_1(&mut self) -> Output1 { + self.numbers + .iter() + .filter_map(|n| { + if self.symbols.contains_key(&(n.y, n.x_min - 1)) + || self.symbols.contains_key(&(n.y, n.x_max)) + || (n.x_min - 1..=n.x_max).any(|xx| { + self.symbols.contains_key(&(n.y - 1, xx)) + || self.symbols.contains_key(&(n.y + 1, xx)) + }) + { + Some(n.value) + } else { + None + } + }) + .sum() + } + + fn part_2(&mut self) -> Output2 { + let mut symbol_counters: HashMap<(usize, usize), Vec> = self + .symbols + .iter() + .filter_map(|((y, x), s)| { + if *s == '*' { + Some(((*y, *x), vec![])) + } else { + None + } + }) + .collect(); + + self.numbers.iter().for_each(|n| { + let mut possible_gears = vec![(n.y, n.x_min - 1), (n.y, n.x_max)]; + + (n.x_min - 1..=n.x_max).for_each(|xx: usize| { + possible_gears.push((n.y - 1, xx)); + possible_gears.push((n.y + 1, xx)); }); for (y, x) in possible_gears { - if symbols.contains_key(&(y, x)) { - symbol_counters.entry((y, x)).or_default().push(*num); - break; + if let Some(nums) = symbol_counters.get_mut(&(y, x)) { + nums.push(n.value); } } });