Day 10
This commit is contained in:
parent
66f1bf92e9
commit
b443e3b01c
1 changed files with 142 additions and 0 deletions
142
src/bin/day10.rs
Normal file
142
src/bin/day10.rs
Normal 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(())
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue