Day 10
authorGreg Burri <greg.burri@gmail.com>
Tue, 10 Dec 2024 15:35:08 +0000 (16:35 +0100)
committerGreg Burri <greg.burri@gmail.com>
Tue, 10 Dec 2024 15:35:08 +0000 (16:35 +0100)
src/day10.rs [new file with mode: 0644]
src/days.rs
src/main.rs

diff --git a/src/day10.rs b/src/day10.rs
new file mode 100644 (file)
index 0000000..a939e60
--- /dev/null
@@ -0,0 +1,122 @@
+use std::io::BufRead;
+
+use nalgebra::DMatrix;
+
+type Map = DMatrix<u32>;
+type Position = (usize, usize);
+
+pub fn read_map(reader: &mut dyn BufRead) -> (Map, Vec<Position>) {
+    let mut map = Map::default();
+    let mut start_positions: Vec<Position> = 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<Position> {
+        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<bool>>,
+    ) -> 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::<bool>::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);
+    }
+}
index b6f3821..2ab38a7 100644 (file)
@@ -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),
+    )
+}
index bc175e6..20fa7d8 100644 (file)
@@ -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,