use itertools::Itertools; pub fn process_part_1(input: &str) -> usize { let trees = parse_trees(input); let rows = trees.len(); let cols = trees[0].len(); (0..rows) .cartesian_product(0..cols) .filter(|&(row, col)| { let height = trees[row][col]; (0..row).all(|i| trees[i][col] < height) // up || (row + 1..rows).all(|i| trees[i][col] < height) // down || (0..col).all(|i| trees[row][i] < height) // left || (col + 1..cols).all(|i| trees[row][i] < height) // right }) .count() } pub fn process_part_2(input: &str) -> usize { let trees = parse_trees(input); let rows = trees.len(); let cols = trees[0].len(); (0..rows) .cartesian_product(0..cols) .map(|(row, col)| { let height = trees[row][col]; let up = match (0..row).rev().position(|i| trees[i][col] >= height) { Some(n) => n + 1, None => row, }; let down = match (row + 1..rows).position(|i| trees[i][col] >= height) { Some(n) => n + 1, None => rows - row - 1, }; let left = match (0..col).rev().position(|i| trees[row][i] >= height) { Some(n) => n + 1, None => col, }; let right = match (col + 1..cols).position(|i| trees[row][i] >= height) { Some(n) => n + 1, None => cols - col - 1, }; up * down * left * right }) .max() .unwrap() } fn parse_trees(input: &str) -> Vec> { input .trim() .split('\n') .map(|i| i.chars().map(|c| c.to_digit(10).unwrap() as u8).collect()) .collect() } #[cfg(test)] mod tests { use super::*; const INPUT: &str = "30373 25512 65332 33549 35390"; #[test] fn day1() { assert_eq!(process_part_1(INPUT), 21); } #[test] fn day2() { assert_eq!(process_part_2(INPUT), 8); } }