/ Rust / 2024 / 04.rs
04.rs
 1  #![feature(test)]
 2  
 3  type Input = Vec<Vec<u8>>;
 4  
 5  const NEIGH: [(isize, isize); 8] = [
 6      (-1, -1),
 7      (-1, 0),
 8      (-1, 1),
 9      (0, -1),
10      (0, 1),
11      (1, -1),
12      (1, 0),
13      (1, 1),
14  ];
15  
16  fn setup(input: &str) -> Input {
17      input.trim().lines().map(|l| l.bytes().collect()).collect()
18  }
19  
20  fn part1(input: &Input) -> usize {
21      let height = input.len() as isize;
22      let width = input[0].len() as isize;
23      (0..height)
24          .flat_map(|i| {
25              (0..width).flat_map(move |j| {
26                  NEIGH.iter().filter(move |&(di, dj)| {
27                      "XMAS".bytes().enumerate().all(|(k, b)| {
28                          let k = k as isize;
29                          let i = i + di * k;
30                          let j = j + dj * k;
31                          (0..height).contains(&i)
32                              && (0..width).contains(&j)
33                              && input[i as usize][j as usize] == b
34                      })
35                  })
36              })
37          })
38          .count()
39  }
40  
41  fn part2(input: &Input) -> usize {
42      let height = input.len();
43      let width = input[0].len();
44      (1..height - 1)
45          .flat_map(|i| {
46              (1..width - 1).filter(move |&j| {
47                  const OUTER: [(u8, u8); 2] = [(b'M', b'S'), (b'S', b'M')];
48                  input[i][j] == b'A'
49                      && OUTER.contains(&(input[i - 1][j - 1], input[i + 1][j + 1]))
50                      && OUTER.contains(&(input[i - 1][j + 1], input[i + 1][j - 1]))
51              })
52          })
53          .count()
54  }
55  
56  aoc::main!(2024, 4, ex: 1);