mod utils; use utils::read_input; fn main() { let input = read_input(); let mut grid: Vec> = input .lines() .map(|x| { x.chars() .map(|x| (x.to_digit(10).unwrap() as u8, false)) .collect() }) .collect(); in_all_directions!(check_vis_along_run, grid); println!( "Part 1: {}", grid.iter() .map(|x| x.iter().filter(|x| x.1).count()) .sum::() ); let mut grid: Vec> = grid .into_iter() .map(|x| x.into_iter().map(|(x, _)| (x, 1)).collect()) .collect(); in_all_directions!(vis_score_along_run, grid); println!( "Part 2: {}", grid.iter() .map(|row| row.iter().map(|(_, vis)| vis).max().unwrap()) .max() .unwrap() ); } fn check_vis_along_run( mut run: impl Iterator, grid: &mut [Vec<(u8, bool)>], ) { let mut curr_height = { let (row_idx, col_idx) = run.next().unwrap(); grid[row_idx][col_idx].1 = true; grid[row_idx][col_idx].0 }; for (row_idx, col_idx) in run { let height = grid[row_idx][col_idx].0; if height > curr_height { curr_height = height; grid[row_idx][col_idx].1 = true; } } } fn vis_score_along_run(run: impl Iterator, grid: &mut [Vec<(u8, u32)>]) { let mut next_values = [0; 10]; for (row_idx, col_idx) in run { let height = grid[row_idx][col_idx].0; grid[row_idx][col_idx].1 *= next_values[height as usize]; for (val, score) in next_values.iter_mut().enumerate() { *score = if *score == 0 || val > height as usize { *score + 1 } else { 1 }; } } } #[macro_use] mod codegen { #[macro_export] macro_rules! in_all_directions { ($f:ident, $grid: ident) => { let grid_rows = $grid.len(); let grid_cols = $grid[0].len(); (0..grid_rows).for_each(|grid_row| { $f( (0..grid_cols).map(move |grid_col| (grid_row, grid_col)), &mut $grid, ); $f( (0..grid_cols) .rev() .map(move |grid_col| (grid_row, grid_col)), &mut $grid, ) }); (0..grid_cols).for_each(|grid_col| { $f( (0..grid_rows).map(move |grid_row| (grid_row, grid_col)), &mut $grid, ); $f( (0..grid_rows) .rev() .map(move |grid_row| (grid_row, grid_col)), &mut $grid, ) }); }; } }