From e0e1bc26e80b6db6c5c6a4c9faffd64b47e3d802 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 9 Dec 2021 12:02:07 +0100 Subject: [PATCH] Simplify implementation day 8 The second part doesn't actually need to start the search at the low points; just iterating everything and keeping track of visited spaces is enough. Now that the iterator is only used in part 1, we inline the iterator to remove some overhead from the code. --- 2021/src/day09.rs | 140 +++++++++++++++++++--------------------------- 1 file changed, 58 insertions(+), 82 deletions(-) diff --git a/2021/src/day09.rs b/2021/src/day09.rs index fdd6e81..33fdecd 100644 --- a/2021/src/day09.rs +++ b/2021/src/day09.rs @@ -1,56 +1,6 @@ use std::cmp::Reverse; use std::io::Read; -struct LowPointsIter<'a> { - lines: &'a [&'a [u8]], - x: usize, - y: usize, -} - -impl<'a> LowPointsIter<'a> { - pub fn new(lines: &'a [&'a [u8]]) -> Self { - Self { lines, x: 0, y: 0 } - } -} - -impl Iterator for LowPointsIter<'_> { - type Item = (usize, usize); - - fn next(&mut self) -> Option { - let lines = self.lines; - - for y in self.y..self.lines.len() { - for x in self.x..self.lines[y].len() { - if x > 0 && lines[y][x - 1] <= lines[y][x] { - continue; - } - - if x + 1 < lines[y].len() && lines[y][x + 1] <= lines[y][x] { - continue; - } - - if y > 0 && lines[y - 1][x] <= lines[y][x] { - continue; - } - - if y + 1 < lines.len() && lines[y + 1][x] <= lines[y][x] { - continue; - } - - self.x = x + 1; - self.y = y; - - return Some((x, y)); - } - self.x = 0; - } - - self.y = lines.len(); - - None - } -} - pub fn part1(input: &mut dyn Read) -> String { let mut buffer = Vec::new(); input.read_to_end(&mut buffer).unwrap(); @@ -60,10 +10,31 @@ pub fn part1(input: &mut dyn Read) -> String { .filter(|s| !s.is_empty()) .collect(); - LowPointsIter::new(&lines) - .map(|(x, y)| 1 + (lines[y][x] - b'0') as i32) - .sum::() - .to_string() + let mut total_danger = 0; + + for y in 0..lines.len() { + for x in 0..lines[y].len() { + if x > 0 && lines[y][x - 1] <= lines[y][x] { + continue; + } + + if x + 1 < lines[y].len() && lines[y][x + 1] <= lines[y][x] { + continue; + } + + if y > 0 && lines[y - 1][x] <= lines[y][x] { + continue; + } + + if y + 1 < lines.len() && lines[y + 1][x] <= lines[y][x] { + continue; + } + + total_danger += 1 + (lines[y][x] - b'0') as i32; + } + } + + total_danger.to_string() } pub fn part2(input: &mut dyn Read) -> String { @@ -83,41 +54,46 @@ pub fn part2(input: &mut dyn Read) -> String { let mut sizes = Vec::with_capacity(4); - for (x, y) in LowPointsIter::new(&lines) { - todo.push((x, y)); + for y in 0..lines.len() { + for x in 0..lines[0].len() { + if visited[y][x] || lines[y][x] == b'9' { + continue; + } - let mut size = 1; - visited[y][x] = true; + todo.push((x, y)); + let mut size = 1; + visited[y][x] = true; - while let Some((x, y)) = todo.pop() { - let mut add = |x: usize, y: usize| { - if lines[y][x] != b'9' && !visited[y][x] { - size += 1; - visited[y][x] = true; - todo.push((x, y)); + while let Some((x, y)) = todo.pop() { + let mut add = |x: usize, y: usize| { + if lines[y][x] != b'9' && !visited[y][x] { + size += 1; + visited[y][x] = true; + todo.push((x, y)); + } + }; + + if x > 0 { + add(x - 1, y); } - }; - if x > 0 { - add(x - 1, y); + if x + 1 < lines[y].len() { + add(x + 1, y); + } + + if y > 0 { + add(x, y - 1) + } + + if y + 1 < lines.len() { + add(x, y + 1); + } } - if x + 1 < lines[y].len() { - add(x + 1, y); - } - - if y > 0 { - add(x, y - 1) - } - - if y + 1 < lines.len() { - add(x, y + 1); - } + sizes.push(Reverse(size)); + sizes.sort_unstable(); + sizes.truncate(3); } - - sizes.push(Reverse(size)); - sizes.sort_unstable(); - sizes.truncate(3); } sizes.into_iter().fold(1, |a, Reverse(b)| a * b).to_string()