This commit is contained in:
Quentin Boyer 2024-12-10 23:07:09 +01:00
parent 66f1bf92e9
commit b443e3b01c

142
src/bin/day10.rs Normal file
View file

@ -0,0 +1,142 @@
use std::{collections::HashSet, time::Instant};
use aoc_2024::{load, print_res};
use arrayvec::ArrayVec;
use bstr::{BString, ByteSlice};
type Parsed = Vec<Vec<u8>>;
#[inline(never)]
pub fn parsing(input: &BString) -> color_eyre::Result<Parsed> {
input
.lines()
.map(|line| {
line.iter()
.map(|&x| match x {
b'0'..=b'9' => Ok(x - b'0'),
_ => Err(color_eyre::eyre::eyre!(
"Unknown character: '{}'",
x as char
)),
})
.collect()
})
.collect()
}
fn neighbours(l: usize, c: usize, map: &Parsed) -> ArrayVec<(usize, usize), 4> {
let mut a = ArrayVec::new();
if l != 0 {
a.push((l - 1, c));
}
if c != 0 {
a.push((l, c - 1));
}
if l + 1 != map.len() {
a.push((l + 1, c))
}
if c + 1 != map[0].len() {
a.push((l, c + 1))
}
a
}
fn trailhead_score(l: usize, c: usize, map: &Parsed) -> usize {
let mut locations = HashSet::new();
locations.insert((l, c));
for (current, _) in (0..9).enumerate() {
let current = current as u8;
let mut new_locations = HashSet::new();
for (l, c) in locations {
assert!(map[l][c] == current);
for (nl, nc) in neighbours(l, c, map) {
if map[nl][nc] == current + 1 {
new_locations.insert((nl, nc));
}
}
}
locations = new_locations;
}
locations.len()
}
#[inline(never)]
pub fn part1(input: Parsed) {
let mut score = 0;
for l in 0..input.len() {
for c in 0..input[0].len() {
if input[l][c] == 0 {
score += trailhead_score(l, c, &input);
}
}
}
print_res!("Total score: {score}")
}
fn trailhead_rating(l: usize, c: usize, map: &Parsed) -> usize {
let mut locations = vec![(l, c)];
for (current, _) in (0..9).enumerate() {
let current = current as u8;
let mut new_locations = Vec::new();
for (l, c) in locations {
assert!(map[l][c] == current);
for (nl, nc) in neighbours(l, c, map) {
if map[nl][nc] == current + 1 {
new_locations.push((nl, nc));
}
}
}
locations = new_locations;
}
locations.len()
}
#[inline(never)]
pub fn part2(input: Parsed) {
let mut rating = 0;
for l in 0..input.len() {
for c in 0..input[0].len() {
if input[l][c] == 0 {
rating += trailhead_rating(l, c, &input);
}
}
}
print_res!("Total rating: {rating}")
}
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(())
}