diff --git a/2022/src/day08.rs b/2022/src/day08.rs index 4c8130b..7ca047b 100644 --- a/2022/src/day08.rs +++ b/2022/src/day08.rs @@ -59,8 +59,65 @@ pub fn part1(input: &[u8]) -> Result { Ok(visible.into_iter().filter(|&b| b).count().to_string()) } -pub fn part2(_input: &[u8]) -> Result { - anyhow::bail!("not implemented") +#[inline] +fn scenery<'a>( + values: impl IntoIterator, + visible: impl IntoIterator, +) { + let mut last_seen = [0; 10]; + + for (i, (&val, score)) in values.into_iter().zip(visible).enumerate() { + let val = val - b'0'; + let visible = i - last_seen[val as usize]; + + if i > 0 { + *score *= visible; + for s in 0..=val { + last_seen[s as usize] = i; + } + } else { + *score = 0; + } + } +} + +pub fn part2(input: &[u8]) -> Result { + let width = input + .iter() + .position(|&b| b == b'\n') + .context("Single row field")?; + let height = input.len() / (width + 1); // Include newlines + + let mut score = vec![1; width * height]; + + // Horizontal striping + for (y, row) in input.chunks_exact(width + 1).enumerate() { + // First, left to right + scenery(&row[..width], &mut score[(y * width)..]); + + // Then right to left + scenery( + row[..width].iter().rev(), + score[(y * width)..(y * width + width)].iter_mut().rev(), + ); + } + + // Vertical striping + for x in 0..width { + // Top to bottom + scenery( + input[x..].iter().step_by(width + 1), + score[x..].iter_mut().step_by(width), + ); + + // Bottom to top + scenery( + input[x..].iter().step_by(width + 1).rev(), + score[x..].iter_mut().step_by(width).rev(), + ) + } + + Ok(score.into_iter().max().context("empty field")?.to_string()) } #[cfg(test)]