From 33472462bd78178ee9e2f870583cbef0a45fe7fc Mon Sep 17 00:00:00 2001 From: Louis Vallat Date: Wed, 4 Dec 2024 23:45:24 +0100 Subject: [PATCH] feat: added day 4 part 1 and 2 Signed-off-by: Louis Vallat --- .gitea/workflows/build_and_run.yml | 2 +- day4/Cargo.toml | 6 ++ day4/src/main.rs | 101 +++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 day4/Cargo.toml create mode 100644 day4/src/main.rs diff --git a/.gitea/workflows/build_and_run.yml b/.gitea/workflows/build_and_run.yml index 8a30cbe..dd96060 100644 --- a/.gitea/workflows/build_and_run.yml +++ b/.gitea/workflows/build_and_run.yml @@ -11,7 +11,7 @@ jobs: name: Challenge for day strategy: matrix: - day_number: [1, 2, 3] + day_number: [1, 2, 3, 4] runs-on: rust-bookworm steps: - name: Check out repository code diff --git a/day4/Cargo.toml b/day4/Cargo.toml new file mode 100644 index 0000000..0ebbbc8 --- /dev/null +++ b/day4/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day4" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/day4/src/main.rs b/day4/src/main.rs new file mode 100644 index 0000000..c656e97 --- /dev/null +++ b/day4/src/main.rs @@ -0,0 +1,101 @@ +use std::{env, fs}; + +fn read_input(path: &str) -> String { + fs::read_to_string(path).expect("Cannot read file.") +} + +fn parse_input(input: &str) -> Vec> { + input + .lines() + .filter(|line| !line.is_empty()) + .map(|line| line.chars().collect()) + .collect() +} + +fn has_word( + word: &str, + matrix: &Vec>, + source: (usize, usize), + direction: (i32, i32), +) -> bool { + let word = word.chars().collect::>(); + let (row, col) = source; + let (i_row, i_col, i_word_len) = (row as i32, col as i32, word.len() as i32); + + if !(0..matrix.len() as i32).contains(&(i_row + ((i_word_len - 1) * direction.0))) + || !(0..matrix[row].len() as i32).contains(&(i_col + ((i_word_len - 1) * direction.1))) + { + return false; + } + + for (offset, c) in word.iter().enumerate() { + let i_offset = offset as i32; + if matrix[(i_row + i_offset * direction.0) as usize] + [(i_col + i_offset * direction.1) as usize] + != *c + { + return false; + } + } + true +} + +fn part_1(matrix: &Vec>) -> u32 { + let mut found = 0; + for (row, line) in matrix.iter().enumerate() { + for (col, c) in line.iter().enumerate() { + if *c != 'X' { + continue; + } + + for i in -1..=1 { + for j in -1..=1 { + if i == 0 && j == 0 { + continue; + } + + if has_word("XMAS", matrix, (row, col), (i, j)) { + found += 1; + } + } + } + } + } + found +} + +fn is_mas(matrix: &Vec>, row: usize, col: usize, flag: bool) -> bool { + if matrix[row][col] != 'A' { + return false; + } + if flag { + (matrix[row - 1][col - 1] == 'M' && matrix[row + 1][col + 1] == 'S') + || (matrix[row - 1][col - 1] == 'S' && matrix[row + 1][col + 1] == 'M') + } else { + (matrix[row + 1][col - 1] == 'M' && matrix[row - 1][col + 1] == 'S') + || (matrix[row + 1][col - 1] == 'S' && matrix[row - 1][col + 1] == 'M') + } +} + +fn part_2(matrix: &Vec>) -> u32 { + let mut found = 0; + for row in 1..(matrix.len() - 1) { + for col in 1..(matrix[row].len() - 1) { + if is_mas(matrix, row, col, true) && is_mas(matrix, row, col, false) { + found += 1; + } + } + } + found +} + +fn main() { + let args: Vec = env::args().collect(); + for arg in args.iter().skip(1) { + let input = read_input(&arg); + let matrix = parse_input(&input); + println!("[{}]", &arg); + println!("\t[Part 1] => Answer is '{}'.", part_1(&matrix)); + println!("\t[Part 2] => Answer is '{}'.", part_2(&matrix)); + } +}