From 64baadd5aa090e00e04bf83422546171ad03c12a Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Tue, 10 Dec 2024 16:35:08 +0100 Subject: [PATCH] Day 10 --- src/day10.rs | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/days.rs | 9 ++++ src/main.rs | 4 +- 3 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 src/day10.rs diff --git a/src/day10.rs b/src/day10.rs new file mode 100644 index 0000000..a939e60 --- /dev/null +++ b/src/day10.rs @@ -0,0 +1,122 @@ +use std::io::BufRead; + +use nalgebra::DMatrix; + +type Map = DMatrix; +type Position = (usize, usize); + +pub fn read_map(reader: &mut dyn BufRead) -> (Map, Vec) { + let mut map = Map::default(); + let mut start_positions: Vec = Vec::new(); + + for (i, l) in reader.lines().enumerate() { + if map.nrows() < i + 1 { + map = map.insert_row(i, 0); + } + for (j, c) in l.unwrap().chars().enumerate() { + if map.ncols() < j + 1 { + map = map.insert_column(j, 0); + } + let level = c.to_digit(10).unwrap(); + map[(i, j)] = level; + if level == 0 { + start_positions.push((i, j)); + } + } + } + + (map, start_positions) +} + +pub fn score(map: &Map, start_positions: &[Position], multiple_paths: bool) -> u32 { + fn neighbors((i, j): Position, ncols: usize, nrows: usize) -> Vec { + let mut positions = Vec::new(); + if i > 0 { + positions.push((i - 1, j)); + } + if i < nrows - 1 { + positions.push((i + 1, j)); + } + if j > 0 { + positions.push((i, j - 1)); + } + if j < ncols - 1 { + positions.push((i, j + 1)); + } + positions + } + + fn get_nb_summits( + (i, j): Position, + map: &Map, + visited: &mut Option<&mut DMatrix>, + ) -> u32 { + if let Some(visited) = visited.as_mut() { + if visited[(i, j)] { + return 0; + } else { + visited[(i, j)] = true; + } + } + + if map[(i, j)] == 9 { + 1 + } else { + neighbors((i, j), map.ncols(), map.nrows()) + .into_iter() + .filter_map(|(i2, j2)| { + if map[(i2, j2)] == map[(i, j)] + 1 { + Some(get_nb_summits((i2, j2), map, visited)) + } else { + None + } + }) + .sum() + } + } + + start_positions + .into_iter() + .map(|pos| { + let mut visited = DMatrix::::repeat(map.nrows(), map.ncols(), false); + let n = get_nb_summits( + *pos, + map, + &mut if multiple_paths { + None + } else { + Some(&mut visited) + }, + ); + n + }) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + static MAP: &str = "89010123 +78121874 +87430965 +96549874 +45678903 +32019012 +01329801 +10456732"; + + #[test] + fn test_part1() { + let (map, start_positions) = read_map(&mut MAP.as_bytes()); + let score = score(&map, &start_positions, false); + assert_eq!(score, 36); + } + + #[test] + fn test_part2() { + let (map, start_positions) = read_map(&mut MAP.as_bytes()); + let score = score(&map, &start_positions, true); + assert_eq!(score, 81); + } +} diff --git a/src/days.rs b/src/days.rs index b6f3821..2ab38a7 100644 --- a/src/days.rs +++ b/src/days.rs @@ -84,3 +84,12 @@ pub fn day09(reader: &mut dyn BufRead) -> String { day09::checksum(&memory_defrag_v2), ) } + +pub fn day10(reader: &mut dyn BufRead) -> String { + let (map, start_positions) = day10::read_map(reader); + format!( + "part1: {}, part2: {}", + day10::score(&map, &start_positions, false), + day10::score(&map, &start_positions, true), + ) +} diff --git a/src/main.rs b/src/main.rs index bc175e6..20fa7d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ mod day06; mod day07; mod day08; mod day09; -// mod day10; +mod day10; // mod day11; // mod day12; // mod day13; @@ -57,7 +57,7 @@ fn main() { days::day07, days::day08, days::day09, - // days::day10, + days::day10, // days::day11, // days::day12, // days::day13, -- 2.45.2