diff --git a/src/days.rs b/src/days.rs index 0958165..21b6c99 100644 --- a/src/days.rs +++ b/src/days.rs @@ -1,7 +1,7 @@ pub mod d1; pub mod d2; pub mod d3; -// pub mod d4; +pub mod d4; // pub mod d5; // pub mod d6; // pub mod d7; diff --git a/src/days/d4.rs b/src/days/d4.rs new file mode 100644 index 0000000..70817d8 --- /dev/null +++ b/src/days/d4.rs @@ -0,0 +1,118 @@ +#![allow(non_upper_case_globals)] +use crate::prelude::*; + +pub type I = Vec>; +pub type O = usize; + +fn _parse (data: &str) -> I { + data.lines().map(|line| line.chars().collect()).collect() +} + +fn _raycast ((y, x): (usize, usize), rows: usize, cols: usize) -> Vec> { + const r: [[(isize, isize); 3]; 8] = [ + [(-1, -1), (-2, -2), (-3, -3)], // UL + [(-1, 0), (-2, 0), (-3, 0)], // U + [(-1, 1), (-2, 2), (-3, 3)], // UR + + [(0, -1), (0, -2), (0, -3)], // L + [(0, 1), (0, 2), (0, 3)], // R + + + [(1, -1), (2, -2), (3, -3)], // DL + [(1, 0), (2, 0), (3, 0)], // D + [(1, 1), (2, 2), (3, 3)], // DR + ]; + + + r.into_iter().filter_map(|e| { + let new = e.into_iter().filter_map(|(dy, dx)| { + let ny = y.checked_add_signed(dy)?; + let nx = x.checked_add_signed(dx)?; + if ny >= rows || nx >= cols { return None; } + Some((ny, nx)) + }).collect_vec(); + if new.len() != 3 { return None } + Some(new) + }).collect() +} + +fn _raycast_2 ((y, x): (usize, usize), rows: usize, cols: usize) -> Vec<(usize, usize)> { + const r: [(isize, isize); 4] = [ + (-1, -1), // UL + (-1, 1), // UR + (1, -1), // DL + (1, 1), // DR + ]; + + let v: Vec<(usize, usize)> = r.into_iter().filter_map(|(dy, dx)| { + let ny = y.checked_add_signed(dy)?; + let nx = x.checked_add_signed(dx)?; + if ny >= rows || nx >= cols { return None; } + Some((ny, nx)) + }).collect(); + + + if v.len() != r.len() { vec![] } else { v } +} + +fn _silver (data: I) -> O { + let rows = data.len(); + let mut count = 0; + for (y, row) in data.iter().enumerate() { + let cols = row.len(); + for (x, &cell) in row.iter().enumerate() { + if cell == 'X' { + count += _raycast((y, x), rows, cols).into_iter().map(|e| format!("X{}", e.iter().map(|&(y, x)| data[y][x]).collect::())).filter(|s| s == "XMAS").count(); + } + } + } + + count +} + +fn _gold (data: I) -> O { + let rows = data.len(); + let mut count = 0; + for (y, row) in data.iter().enumerate() { + let cols = row.len(); + for (x, &cell) in row.iter().enumerate() { + if cell == 'A' { + let rays = _raycast_2((y, x), rows, cols).into_iter().map(|(y, x)| (data[y][x], (y, x))).collect_vec(); + let ms = rays.iter().filter(|(c, _)| *c == 'M').collect_vec(); + if ms.len() == 2 && + rays.iter().filter(|(c, _)| *c == 'S').count() == 2 && + (ms[0].1.0 == ms[1].1.0 || ms[0].1.1 == ms[1].1.1) { + count += 1; + } + } + } + } + + count +} + +#[cfg(test)] +mod test { + use super::*; + + fn read () -> I { + let data = inc!(4); + _parse(data) + } + + #[test] + fn silver () { + let data = read(); + let ans = _silver(data); + + assert_eq!(ans, 2603) + } + + #[test] + fn gold () { + let data = read(); + let ans = _gold(data); + + assert_eq!(ans, 1965) + } +}