use std::io; fn main() -> io::Result<()> { let grid = io::stdin() .lines() .flatten() .map(|line| line.chars().collect()) .collect::>>(); let grid = Grid(grid); let silver: usize = silver(&grid); let gold: usize = gold(&grid); println!("silver: {silver}"); println!("gold: {gold}"); return Ok(()); } struct Grid(Vec>); impl Grid { fn at(&self, (x, y): (isize, isize)) -> Option<&char> { self.0 .get(usize::try_from(y).ok()?)? .get(usize::try_from(x).ok()?) } fn check<'a>( &self, (x, y): (isize, isize), mut pat: impl Iterator, ) -> bool { pat.all(|((dx, dy), ch)| self.at((x + dx, y + dy)).is_some_and(|c| c == ch)) } fn pts(&self) -> impl Iterator + use<'_> { (0..self.0[0].len()).flat_map(|x| (0..self.0.len()).map(move |y| (x as isize, y as isize))) } } fn silver(grid: &Grid) -> usize { let dirs = vec![ (-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1), ]; let xmases: Vec> = dirs .iter() .map(|(dx, dy)| { (1..4) .map(move |n| (dx * n, dy * n)) .zip("MAS".chars()) .collect() }) .collect(); grid.pts() .filter(|&p| grid.at(p).is_some_and(|&c| c == 'X')) .flat_map(|p| xmases.iter().map(move |xmas| grid.check(p, xmas.iter()))) .filter(|p| *p) .count() } fn gold(grid: &Grid) -> usize { 0 }