Day 4
This commit is contained in:
parent
8f6f15c473
commit
345914c97a
1 changed files with 107 additions and 0 deletions
107
src/bin/day4.rs
Normal file
107
src/bin/day4.rs
Normal 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(())
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue