const XMAS: &str = "XMAS"; const MAS: &str = "MAS"; type Matrix = Vec>; type Position = (usize, usize); type RowXmas = [Position; XMAS.len()]; type RowMas = [Position; MAS.len()]; fn check_xmas<'a, I>(m: &Matrix, it: I) -> bool where I: Iterator, { for (c, (i, j)) in XMAS.chars().zip(it) { if m[*i][*j] != c { return false; } } true } fn offplus(x: usize, y: isize) -> usize { (x as isize + y) as usize } fn rows_latdiag_from(p: Position, max_x: usize, max_y: usize) -> Vec { let mut rs: Vec = vec![]; // Horizontal / vertical / diagonal for (p0, (di, dj)) in [ (p, (0, 1)), // horizontal, left-to-right (p, (1, 0)), // vertical, top-down (p, (1, 1)), // diag from p, top-down and left-to-right ((p.0, p.1 + XMAS.len() - 1), (1, -1isize)), // the other diag, top-down and right-to-left ] { // Bounds check let max_off = XMAS.len(); if p0.0 + di * max_off > max_x || (dj > 0 && offplus(p0.1, dj * max_off as isize) > max_y) || p0.1 >= max_y { continue; } let mut p_acc = p0; let mut ps = [(0, 0); XMAS.len()]; for idx in 0..ps.len() { ps[idx].0 = p_acc.0; ps[idx].1 = p_acc.1; p_acc = (p_acc.0 + di, offplus(p_acc.1, dj)); } rs.push(ps); } rs } pub fn p1(input: &str) -> String { let m: Matrix = input.lines().map(|row| row.chars().collect()).collect(); let mut result = 0; for i in 0..m.len() { for j in 0..m[i].len() { let p = (i, j); for row in rows_latdiag_from(p, m.len(), m[i].len()) { if check_xmas(&m, row.iter()) || check_xmas(&m, row.iter().rev()) { result += 1; } } } } result.to_string() } fn check_mas<'a, I>(m: &Matrix, it: I) -> bool where I: Iterator, { for (c, (i, j)) in MAS.chars().zip(it) { if m[*i][*j] != c { return false; } } true } fn rows_diag_from(p: Position, max_x: usize, max_y: usize) -> Vec { let mut rs: Vec = vec![]; // Horizontal / vertical / diagonal for (p0, (di, dj)) in [ (p, (1, 1)), // diag from p, top-down and left-to-right ((p.0, p.1 + MAS.len() - 1), (1, -1isize)), // the other diag, top-down and right-to-left ] { // Bounds check let max_off = MAS.len(); if p0.0 + di * max_off > max_x || (dj > 0 && offplus(p0.1, dj * max_off as isize) > max_y) || p0.1 >= max_y { continue; } let mut p_acc = p0; let mut ps = [(0, 0); MAS.len()]; for idx in 0..ps.len() { ps[idx].0 = p_acc.0; ps[idx].1 = p_acc.1; p_acc = (p_acc.0 + di, offplus(p_acc.1, dj)); } rs.push(ps); } rs } pub fn p2(input: &str) -> String { let m: Matrix = input.lines().map(|row| row.chars().collect()).collect(); let mut result = 0; for i in 0..=m.len() - MAS.len() { for j in 0..=m[i].len() - MAS.len() { let p = (i, j); let rows = rows_diag_from(p, m.len(), m[i].len()); if rows.iter().all(|r| check_mas(&m, r.iter()) || check_mas(&m, r.iter().rev())) { result += 1; } } } result.to_string() }