From 345914c97a911932fa54ccc72dc7c2b7bb19c104 Mon Sep 17 00:00:00 2001 From: Quentin Boyer Date: Thu, 5 Dec 2024 00:02:15 +0100 Subject: [PATCH] Day 4 --- src/bin/day4.rs | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/bin/day4.rs diff --git a/src/bin/day4.rs b/src/bin/day4.rs new file mode 100644 index 0000000..9fa5852 --- /dev/null +++ b/src/bin/day4.rs @@ -0,0 +1,107 @@ +use std::time::Instant; + +use aoc_2024::{load, print_res}; +use bstr::{BString, ByteSlice}; +use itertools::Itertools; + +type Parsed<'a> = Vec<&'a [u8]>; + +pub fn parsing(input: &BString) -> color_eyre::Result { + Ok(input.lines().collect()) +} + +fn rays_index( + x: usize, + y: usize, + x_len: usize, + y_len: usize, + ray_length: usize, +) -> impl Iterator> { + let x = x as isize; + let y = y as isize; + let extent = move |d, c| d * (ray_length as isize - 1) + c; + + (-1..=1) + .filter(move |&dx| extent(dx, x) >= 0 && extent(dx, x) < x_len as isize) + .flat_map(move |dx| { + (-1..=1) + .filter(move |&dy| extent(dy, y) >= 0 && extent(dy, y) < y_len as isize) + .map(move |dy| { + (0..(ray_length as isize)) + .map(move |n| ((x + dx * n) as usize, (y + dy * n) as usize)) + }) + }) +} + +fn rays<'a, T>( + x: usize, + y: usize, + table: &'a [&'a [T]], + ray_length: usize, +) -> impl Iterator> { + rays_index(x, y, table.len(), table[0].len(), ray_length) + .map(|ray| ray.map(|(x, y)| &table[x][y])) +} + +pub fn part1(input: Parsed) { + let expected = b"XMAS"; + let mut ray_count = 0; + + for i in 0..input.len() { + for j in 0..input[0].len() { + let rays_at = rays(i, j, &input, expected.len()) + .map(|ray| ray.zip_eq(expected).all(|(&a, &b)| a == b)) + .filter(|&x| x) + .count(); + ray_count += rays_at; + } + } + + print_res!("Word count: {ray_count}"); +} + +pub fn part2(input: Parsed) { + let mut cross_count = 0; + let expected = *b"MAS"; + let reversed = { + let mut ex = expected; + ex.reverse(); + ex + }; + + for i in 1..(input.len() - 1) { + for j in 1..(input.len() - 1) { + let slash = [input[i - 1][j - 1], input[i][j], input[i + 1][j + 1]]; + let backslash = [input[i - 1][j + 1], input[i][j], input[i + 1][j - 1]]; + + if (slash == expected || slash == reversed) + && (backslash == expected || backslash == reversed) + { + cross_count += 1; + } + } + } + + print_res!("Number of 'MAS' crosses: {cross_count}"); +} + +pub fn main() -> color_eyre::Result<()> { + let context = load()?; + + let start = Instant::now(); + let parsed = parsing(&context.input)?; + let elapsed = humantime::format_duration(start.elapsed()); + + let start = Instant::now(); + if context.part == 1 { + part1(parsed); + } else { + part2(parsed); + } + let elapsed_part = humantime::format_duration(start.elapsed()); + + println!(" Parsing: {elapsed}"); + println!(" Solving: {elapsed_part}"); + + Ok(()) +}