2024: day 10: part 1 and 2: rust

This commit is contained in:
Samuel Ortion 2024-12-15 11:18:27 +01:00
parent 9347243eee
commit 8367b63c53
Signed by: sortion
GPG Key ID: 9B02406F8C4FB765
2 changed files with 102 additions and 0 deletions

View File

@ -0,0 +1,6 @@
[package]
name = "day10"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@ -0,0 +1,96 @@
use std::collections::BTreeSet;
fn parse_map(string: String) -> Vec<Vec<u32>> {
let mut map: Vec<Vec<u32>> = Vec::new();
for line in string.lines() {
let mut map_slice: Vec<u32> = Vec::new();
for letter in line.chars() {
let height: u32 = letter.to_digit(10).unwrap();
map_slice.push(height);
}
map.push(map_slice);
}
map
}
fn is_in_bound(x: isize, y: isize, width: usize, height: usize) -> bool {
x >= 0 && y >= 0 && y < height as isize && x < width as isize
}
fn trailhead_score(start_x: usize, start_y: usize, map: &Vec<Vec<u32>>) -> u32 {
let mut visited: BTreeSet<(usize, usize)> = BTreeSet::new();
let mut score: u32 = 0;
let mut queue: Vec<(usize, usize)> = Vec::new();
queue.push((start_x, start_y));
let moves: [(isize, isize); 4] = [(-1, 0), (0, -1), (1, 0), (0, 1)];
while !queue.is_empty() {
if let Some((x, y)) = queue.pop() {
if map[y][x] == 9 {
score += 1;
}
for (dx, dy) in moves {
let new_x = x as isize + dx;
let new_y = y as isize + dy;
if is_in_bound(new_x, new_y, map[0].len(), map.len())
&& map[new_y as usize][new_x as usize] > map[y][x]
&& map[new_y as usize][new_x as usize] - map[y][x] == 1
&& !visited.contains(&(new_x as usize, new_y as usize)) {
queue.push((new_x as usize, new_y as usize));
}
}
visited.insert((x as usize, y as usize));
}
}
score
}
fn trailhead_paths(x: usize, y: usize, map: &Vec<Vec<u32>>) -> u32 {
if map[y][x] == 9 {
return 1;
} else {
let moves: [(isize, isize); 4] = [(-1, 0), (0, -1), (1, 0), (0, 1)];
let mut paths: u32 = 0;
for (dx, dy) in moves {
let new_x = x as isize + dx;
let new_y = y as isize + dy;
if is_in_bound(new_x, new_y, map[0].len(), map.len())
&& map[new_y as usize][new_x as usize] > map[y][x]
&& map[new_y as usize][new_x as usize] - map[y][x] == 1 {
let p = trailhead_paths(new_x as usize, new_y as usize, map);
paths += p;
}
}
return paths;
}
}
fn find_trailheads(map: &Vec<Vec<u32>>) -> Vec<(usize, usize)> {
let mut trailheads: Vec<(usize, usize)> = Vec::new();
for y in 0..map.len() {
for x in 0..map[y].len() {
if map[y][x] == 0 {
trailheads.push((x, y));
}
}
}
trailheads
}
fn main() -> std::io::Result<()> {
let input = std::io::read_to_string(std::io::stdin())?;
let map = parse_map(input);
let trailheads = find_trailheads(&map);
// Part 1.
let mut score = 0;
for (start_x, start_y) in &trailheads {
score += trailhead_score(*start_x, *start_y, &map);
}
println!("{}", score);
// Part 2.
let mut paths = 0;
for (start_x, start_y) in &trailheads {
paths += trailhead_paths(*start_x, *start_y, &map);
}
println!("{}", paths);
Ok(())
}