118 Zeilen
3,4 KiB
Rust
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);
|
|
}
|
|
}
|