diff --git a/2022/rust/src/solutions/day08.rs b/2022/rust/src/solutions/day08.rs index 4c35cab..da02468 100644 --- a/2022/rust/src/solutions/day08.rs +++ b/2022/rust/src/solutions/day08.rs @@ -1,3 +1,5 @@ +use std::cmp::max; +use std::collections::HashMap; use crate::utils; @@ -31,11 +33,7 @@ fn create_mask(data: &[Vec]) -> Vec> { let mut visible: Vec> = (0..rows) .into_iter() - .map(|_| (0..cols) - .into_iter() - .map(|_| false) - .collect() - ) + .map(|_| (0..cols).into_iter().map(|_| false).collect()) .collect(); for row in 0..rows { @@ -63,18 +61,74 @@ fn create_mask(data: &[Vec]) -> Vec> { fn solve1(data: &[Vec]) -> usize { - let mask = create_mask(data); + create_mask(data).into_iter().map(|row| row.iter().filter(|&e| *e).count()).sum() +} - mask.into_iter() - .map(|row| row.iter() - .filter(|&e| *e) - .count() - ) - .sum() +#[inline(always)] +fn find_limit( + data: &[Vec], + last_heights: &mut HashMap, + row: usize, + col: usize +) -> usize { + let mut limit = 0; + for h in data[row][col]..=9 { + if let Some(since) = last_heights.get(&h) { + limit = max(limit, *since); + } + }; + limit +} + +fn find_scores(data: &[Vec]) -> Vec> { + let rows = data.len(); + let cols = data[0].len(); + + let mut scores: Vec> = (0..rows) + .into_iter() + .map(|_| (0..cols).into_iter().map(|_| 1).collect()) + .collect(); + + for row in 0..rows { + let mut last_heights: HashMap = HashMap::new(); + for col in 0..cols { + let limit = find_limit(data, &mut last_heights, row, col); + scores[row][col] = scores[row][col] * (col - limit) as i32; + last_heights.insert(data[row][col], col); + }; + let mut last_heights: HashMap = HashMap::new(); + for col in (0..cols).rev() { + let limit = find_limit(data, &mut last_heights, row, col); + let limit = if limit == 0 { cols - 1 } else { limit }; + scores[row][col] = scores[row][col] * (limit - col) as i32; + last_heights.insert(data[row][col], col); + }; + }; + + for col in 0..cols { + let mut last_heights: HashMap = HashMap::new(); + for row in 0..rows { + let limit = find_limit(data, &mut last_heights, row, col); + scores[row][col] = scores[row][col] * (row - limit) as i32; + last_heights.insert(data[row][col], row); + }; + let mut last_heights: HashMap = HashMap::new(); + for row in (0..cols).rev() { + let limit = find_limit(data, &mut last_heights, row, col); + let limit = if limit == 0 { rows - 1 } else { limit }; + scores[row][col] = scores[row][col] * (limit - row) as i32; + last_heights.insert(data[row][col], row); + }; + }; + + scores } fn solve2(data: &[Vec]) -> i32 { - 2 + let scores = find_scores(data); + + let reducer = |a, b| max(a, b); + scores.into_iter().map(|row| row.iter().copied().reduce(reducer).unwrap()).reduce(reducer).unwrap() } @@ -110,6 +164,9 @@ mod tests { #[test] fn part2() { let data = parse_data(DATA); - assert_eq!(2, solve2(&data)); + let scores = find_scores(&data); + assert_eq!(4, scores[1][2]); + assert_eq!(8, scores[3][2]); + assert_eq!(8, solve2(&data)); } }