adventofcode/days/2024/10.rs

118 Zeilen
3,4 KiB
Rust

use advent_of_code::{
strings::{char_to_num, convert_to_array},
Kartesian, KartesianDirection, MaximumFromMap,
};
use advent_of_code_macros::include_aoc;
include_aoc!(2024, 10);
type Trail = Vec<Kartesian<u32>>;
type Map = Vec<Vec<u32>>;
fn get_height(line: &str) -> Vec<u32> {
let mut numbers = Vec::new();
for c in line.chars() {
numbers.push(match c {
'.' => 11,
c => char_to_num(c),
});
}
numbers
}
fn follow_trail(position: Kartesian<u32>, number: u32, current: Trail, trails: &mut Vec<Trail>, map: &Map) {
let max = Kartesian::maximum(map);
let mut new;
#[cfg(debug_assertions)]
if map[position.x as usize][position.y as usize] != number {
panic!("Positition is not correct")
}
let mut newposition;
let mut found = false;
for dir in KartesianDirection::iter(false, false, true) {
newposition = match position.move_dir(dir.vector_abs(), dir) {
None => continue,
Some(pos) => {
if pos.x >= max.x || pos.y >= max.y {
continue;
}
pos
},
};
if map[newposition.x as usize][newposition.y as usize] == number + 1 {
found = true;
new = current.clone();
new.push(newposition);
follow_trail(newposition, number + 1, new, trails, map);
}
}
if !found {
trails.push(current);
}
}
fn find_trails(map: &Map) -> Vec<Vec<Trail>> {
let mut trails = Vec::new();
for (x, line) in map.iter().enumerate() {
for (y, column) in line.iter().cloned().enumerate() {
if column == 0 {
let trailhead = Kartesian::new(x as u32, y as u32);
let mut traillist = Vec::<Trail>::new();
follow_trail(trailhead, 0, vec![trailhead], &mut traillist, map);
trails.push(traillist);
}
}
}
trails
}
fn score_trail(trails: &Vec<Trail>) -> u32 {
let mut highest_points = Vec::new();
let mut last;
for trail in trails {
last = trail.last().unwrap().clone();
if trail.len() == 10 && !highest_points.contains(&last) {
highest_points.push(last);
}
}
highest_points.len() as u32
}
fn main() {
let map = convert_to_array::<_, _, '\n'>(DATA, get_height);
let trails = find_trails(&map);
let mut score = 0;
let mut rating = 0;
for traillist in trails {
score += score_trail(&traillist);
rating += traillist.iter().filter(|x| x.len() == 10).count();
}
println!("Total Score of Map: {}", score);
println!("Total Rating of Map: {}", rating);
}
#[cfg(test)]
mod test {
use super::*;
include_aoc!(MAP, 2024, 10, true);
const SCORE: u32 = 36;
#[test]
fn test_simple() {
let mut score = 0;
for trails in find_trails(&convert_to_array::<_, _, '\n'>(MAP, get_height)).values().cloned() {
for trail in trails.clone() {
for (i, point) in trail.iter().enumerate() {
print!("{}", point);
if i != trail.len() - 1 {
print!(" -> ")
}
}
println!();
}
score += score_trail(trails);
}
assert!(score == SCORE, "Score of the map did not match the expected value: {} == {}\n{}", score, SCORE, MAP);
}
}