Skip to content

Commit

Permalink
AoC24: Solve day 4 part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
guerinoni committed Dec 7, 2024
1 parent a90944f commit 7a14496
Show file tree
Hide file tree
Showing 3 changed files with 360 additions and 0 deletions.
212 changes: 212 additions & 0 deletions advent-of-code-2024/src/day04.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
// --- Day 4: Ceres Search ---

// "Looks like the Chief's not here. Next!" One of The Historians pulls out a device and pushes the only button on it. After a brief flash, you recognize the interior of the Ceres monitoring station!

// As the search for the Chief continues, a small Elf who lives on the station tugs on your shirt; she'd like to know if you could help her with her word search (your puzzle input). She only has to find one word: XMAS.

// This word search allows words to be horizontal, vertical, diagonal, written backwards, or even overlapping other words. It's a little unusual, though, as you don't merely need to find one instance of XMAS - you need to find all of them. Here are a few ways XMAS might appear, where irrelevant characters have been replaced with .:

// ..X...
// .SAMX.
// .A..A.
// XMAS.S
// .X....

// The actual word search will be full of letters instead. For example:

// MMMSXXMASM
// MSAMXMSMSA
// AMXSXMAAMM
// MSAMASMSMX
// XMASAMXAMM
// XXAMMXXAMA
// SMSMSASXSS
// SAXAMASAAA
// MAMMMXMMMM
// MXMXAXMASX

// In this word search, XMAS occurs a total of 18 times; here's the same word search again, but where letters not involved in any XMAS have been replaced with .:

// ....XXMAS.
// .SAMXMS...
// ...S..A...
// ..A.A.MS.X
// XMASAMX.MM
// X.....XA.A
// S.S.S.S.SS
// .A.A.A.A.A
// ..M.M.M.MM
// .X.X.XMASX

// Take a look at the little Elf's word search. How many times does XMAS appear?

// --- Part Two ---

// The Elf looks quizzically at you. Did you misunderstand the assignment?

// Looking for the instructions, you flip over the word search to find that this isn't actually an XMAS puzzle; it's an X-MAS puzzle in which you're supposed to find two MAS in the shape of an X. One way to achieve that is like this:

// M.S
// .A.
// M.S

// Irrelevant characters have again been replaced with . in the above diagram. Within the X, each MAS can be written forwards or backwards.

// Here's the same example from before, but this time all of the X-MASes have been kept instead:

// .M.S......
// ..A..MSMS.
// .M.S.MAA..
// ..A.ASMSM.
// .M.S.M....
// ..........
// S.S.S.S.S.
// .A.A.A.A..
// M.M.M.M.M.
// ..........

// In this example, an X-MAS appears 9 times.

// Flip the word search from the instructions back over to the word search side and try again. How many times does an X-MAS appear?


#[allow(clippy::cast_possible_wrap)]
fn try_right(matrix: &[Vec<char>], x: usize, y: usize) -> bool {
if x + 3 >= matrix[y].len() {
return false;
}

matrix[y][x + 1] == 'M' && matrix[y][x + 2] == 'A' && matrix[y][x + 3] == 'S'
}

#[allow(clippy::cast_possible_wrap)]
fn try_left(matrix: &[Vec<char>], x: usize, y: usize) -> bool {
if (x as isize) - 3 < 0 {
return false;
}

matrix[y][x - 1] == 'M' && matrix[y][x - 2] == 'A' && matrix[y][x - 3] == 'S'
}

#[allow(clippy::cast_possible_wrap)]
fn try_down(matrix: &[Vec<char>], x: usize, y: usize) -> bool {
if y + 3 >= matrix.len() {
return false;
}

matrix[y + 1][x] == 'M' && matrix[y + 2][x] == 'A' && matrix[y + 3][x] == 'S'
}

#[allow(clippy::cast_possible_wrap)]
fn try_up(matrix: &[Vec<char>], x: usize, y: usize) -> bool {
if (y as isize) - 3 < 0 {
return false;
}

matrix[y - 1][x] == 'M' && matrix[y - 2][x] == 'A' && matrix[y - 3][x] == 'S'
}
#[allow(clippy::cast_possible_wrap)]
fn try_right_down(matrix: &[Vec<char>], x: usize, y: usize) -> bool {
if x + 3 >= matrix[y].len() || y + 3 >= matrix.len() {
return false;
}

matrix[y + 1][x + 1] == 'M' && matrix[y + 2][x + 2] == 'A' && matrix[y + 3][x + 3] == 'S'
}

#[allow(clippy::cast_possible_wrap)]
fn try_left_down(matrix: &[Vec<char>], x: usize, y: usize) -> bool {
if (x as isize) - 3 < 0 || y + 3 >= matrix.len() {
return false;
}

matrix[y + 1][x - 1] == 'M' && matrix[y + 2][x - 2] == 'A' && matrix[y + 3][x - 3] == 'S'
}
#[allow(clippy::cast_possible_wrap)]
fn try_right_up(matrix: &[Vec<char>], x: usize, y: usize) -> bool {
if x + 3 >= matrix[y].len() || (y as isize) - 3 < 0 {
return false;
}

matrix[y - 1][x + 1] == 'M' && matrix[y - 2][x + 2] == 'A' && matrix[y - 3][x + 3] == 'S'
}
#[allow(clippy::cast_possible_wrap)]
fn try_left_up(matrix: &[Vec<char>], x: usize, y: usize) -> bool {
if (x as isize) - 3 < 0 || (y as isize) - 3 < 0 {
return false;
}

matrix[y - 1][x - 1] == 'M' && matrix[y - 2][x - 2] == 'A' && matrix[y - 3][x - 3] == 'S'
}

// It returs the number of XMAS found
fn find_xmas(matrix: &[Vec<char>], x: usize, y: usize) -> u32 {
let r = try_right(matrix, x, y);
let l = try_left(matrix, x, y);
let d = try_down(matrix, x, y);
let u = try_up(matrix, x, y);
let rd = try_right_down(matrix, x, y);
let ld = try_left_down(matrix, x, y);
let ru = try_right_up(matrix, x, y);
let lu = try_left_up(matrix, x, y);

r as u32 + l as u32 + d as u32 + u as u32 + rd as u32 + ld as u32 + ru as u32 + lu as u32
}

#[must_use]
pub fn solve(input: &str) -> (u32, u32) {
let matrix = input
.lines()
.map(|line| line.chars().collect::<Vec<_>>())
.collect::<Vec<_>>();

let mut p1 = 0;
let (mut x, mut y) = (0, 0);

let horizontal_len = matrix[0].len();
let vertical_len = matrix.len();

loop {
if y >= vertical_len {
// finished
break;
}

if x >= horizontal_len {
// next line
x = 0;
y += 1;
continue;
}

let ch = matrix[y][x];
if ch == 'X' {
p1 += find_xmas(&matrix, x, y);
}

x += 1;
}

(p1, 0)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn sample() {
let input = r#"MMMSXXMASM
MSAMXMSMSA
AMXSXMAAMM
MSAMASMSMX
XMASAMXAMM
XXAMMXXAMA
SMSMSASXSS
SAXAMASAAA
MAMMMXMMMM
MXMXAXMASX"#;

assert_eq!(solve(input), (18, 0));
}
}
8 changes: 8 additions & 0 deletions advent-of-code-2024/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod day01;
mod day02;
mod day03;
mod day04;
mod memory;

fn main() {
Expand Down Expand Up @@ -30,4 +31,11 @@ fn main() {
println!(" Part 2: {p2}");

memory::print("after day03");

let (p1, p2) = day04::solve(include_str!("./testdata/day04"));
println!("Day 04");
println!(" Part 1: {p1}");
println!(" Part 2: {p2}");

memory::print("after day04");
}
Loading

0 comments on commit 7a14496

Please sign in to comment.