Files
contests/advent_of_code/2024/4/src/main.rs

154 lines
3.6 KiB
Rust

use std::cmp::{max, min};
fn parse(input: &str) -> Vec<Vec<char>> {
input.lines().map(|s| s.chars().collect()).collect()
}
fn check_xmas(chars: &Vec<Vec<char>>, start: &(i32, i32), direction: (i32, i32)) -> bool {
let h = chars.len() as i32;
let w = chars[0].len() as i32;
if start.0 + 3 * direction.0 < 0
|| start.0 + 3 * direction.0 >= w
|| start.1 + 3 * direction.1 < 0
|| start.1 + 3 * direction.1 >= h
{
return false;
}
let xmas = vec!['X', 'M', 'A', 'S'];
for x in 0..4 {
let cur_pos = (start.0 + x * direction.0, start.1 + x * direction.1);
if chars[cur_pos.1 as usize][cur_pos.0 as usize] != xmas[x as usize] {
return false;
}
}
true
}
fn solve_1(input: &str) -> usize {
let input = parse(input);
let h = input.len() as i32;
let w = input[0].len() as i32;
let mut result = 0;
for j in 0..h {
for i in 0..w {
if input[j as usize][i as usize] == 'X' {
for ii in max(0, i - 1)..=min(i + 1, w - 1) {
for jj in max(0, j - 1)..=min(j + 1, h - 1) {
if input[jj as usize][ii as usize] == 'M' {
let dir = (ii - i, jj - j);
if check_xmas(&input, &(i, j), dir) {
result += 1;
}
}
}
}
}
}
}
result
}
fn check_x_mas(chars: &Vec<Vec<char>>, candidate: (i32, i32)) -> usize {
let h = chars.len() as i32;
let w = chars[0].len() as i32;
let (x, y) = candidate;
if x == 0 || x == w - 1 || y == 0 || y == h - 1 {
return 0;
}
let mut result = 0;
let mut diagonal_ms = vec![];
let mut diagonal_ss = vec![];
for i in 0..2 {
for j in 0..2 {
let coord = (x as usize - 1 + 2 * i, y as usize - 1 + 2 * j);
match chars[coord.1][coord.0] {
'M' => diagonal_ms.push(coord),
'S' => diagonal_ss.push(coord),
_ => (),
}
}
}
if diagonal_ms.len() >= 2 && diagonal_ss.len() >= 2 {
if diagonal_ms
.into_iter()
.filter(|&(cx, cy)| {
let x_diff = cx as i32 - candidate.0;
let y_diff = cy as i32 - candidate.1;
diagonal_ss.contains(&(
(candidate.0 - x_diff) as usize,
(candidate.1 - y_diff) as usize,
))
})
.count()
== 2
{
result += 1;
}
}
result
}
fn solve_2(input: &str) -> usize {
let input = parse(input);
let h = input.len() as i32;
let w = input[0].len() as i32;
let mut result = 0;
for j in 0..h {
for i in 0..w {
if input[j as usize][i as usize] == 'A' {
result += check_x_mas(&input, (i, j));
}
}
}
result
}
fn main() {
println!("Hello, this is Patrick!");
let input = include_str!("../input.txt");
let result_1 = solve_1(input);
println!("The number of XMASs is {}", result_1);
let result_2 = solve_2(input);
println!("The number of X-MASs is {}", result_2);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input), 18);
}
#[test]
fn test_2() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_2(test_input), 9);
}
}