This commit is contained in:
Quentin Boyer 2024-12-05 00:02:15 +01:00
parent 8f6f15c473
commit 345914c97a

107
src/bin/day4.rs Normal file
View file

@ -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<Parsed> {
Ok(input.lines().collect())
}
fn rays_index(
x: usize,
y: usize,
x_len: usize,
y_len: usize,
ray_length: usize,
) -> impl Iterator<Item = impl Iterator<Item = (usize, usize)>> {
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<Item = impl Iterator<Item = &'a T>> {
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(())
}