diff --git a/input/day10_simple.test.txt b/input/day10_simple.test.txt new file mode 100644 index 0000000..16c5076 --- /dev/null +++ b/input/day10_simple.test.txt @@ -0,0 +1,7 @@ +..90..9 +...1.98 +...2..7 +6543456 +765.987 +876.... +987.... \ No newline at end of file diff --git a/input/day10_simple2.test.txt b/input/day10_simple2.test.txt new file mode 100644 index 0000000..98ab931 --- /dev/null +++ b/input/day10_simple2.test.txt @@ -0,0 +1,7 @@ +.....0. +..4321. +..5..2. +..6543. +..7..4. +..8765. +..9.... \ No newline at end of file diff --git a/src/day10.rs b/src/day10.rs index 0dd7bd9..5f73aef 100644 --- a/src/day10.rs +++ b/src/day10.rs @@ -1,4 +1,9 @@ -use crate::spatial::{Point, adjacent_cardinal, adjacent_cardinal_points, all_coords, flood}; +use itertools::Itertools; + +use crate::spatial::{ + Point, adjacent_cardinal, adjacent_cardinal_points, all_coords, flood, paths_to_each_point, + print_grid, +}; use std::collections::{BTreeSet, HashMap}; pub fn day10_part1(input: &str) -> String { @@ -13,7 +18,24 @@ pub fn day10_part1(input: &str) -> String { } pub fn day10_part2(input: &str) -> String { - todo!() + let topomap = parse(input); + let digraph = topomap_to_digraph(&topomap); + let ratings = all_coords(topomap[0].len(), topomap.len()) + .filter(|pt| topomap[pt.row][pt.col] == 0) + .map(|pt| paths_to_each_point(&digraph, pt)) + .filter(|grid| { + all_coords(topomap[0].len(), topomap.len()) + .any(|pt| topomap[pt.row][pt.col] == 9 && !grid[pt.row][pt.col].is_empty()) + }) + .map(|grid| { + all_coords(topomap[0].len(), topomap.len()) + .filter(|pt| topomap[pt.row][pt.col] == 9) + .map(|pt| grid[pt.row][pt.col].len()) + .sum::() + }) + .collect_vec(); + dbg!(&ratings); + ratings.iter().sum::().to_string() } fn parse(input: &str) -> Vec> { @@ -21,7 +43,7 @@ fn parse(input: &str) -> Vec> { .lines() .map(|line| { line.chars() - .map(|c| c.to_digit(10).unwrap() as u8) + .map(|c| c.to_digit(10).unwrap_or(11) as u8) .collect() }) .collect() diff --git a/src/lib.rs b/src/lib.rs index 6ff18d1..8cbf02f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -359,13 +359,17 @@ mod tests { let result = day10::day10_part1(include_str!("../input/day10.txt")); assert_eq!(result, "820"); } - // #[test] - // fn day10_part2_test() { - // let test_result = day10::day10_part2(include_str!("../input/day10.test.txt")); - // assert_eq!(test_result, "2858"); - // // let result = day10::day10_part2(include_str!("../input/day10.txt")); - // // assert_eq!(result, "6476642796832"); - // } + #[test] + fn day10_part2_test() { + let test_result = day10::day10_part2(include_str!("../input/day10_simple2.test.txt")); + assert_eq!(test_result, "3"); + let test_result = day10::day10_part2(include_str!("../input/day10_simple.test.txt")); + assert_eq!(test_result, "13"); + let test_result = day10::day10_part2(include_str!("../input/day10.test.txt")); + assert_eq!(test_result, "81"); + let result = day10::day10_part2(include_str!("../input/day10.txt")); + assert_eq!(result, "1786"); + } #[test] fn day9_part1_test() { diff --git a/src/spatial.rs b/src/spatial.rs index e538a86..e73a67e 100644 --- a/src/spatial.rs +++ b/src/spatial.rs @@ -7,6 +7,13 @@ pub struct Point { pub row: usize, pub col: usize, } + +impl ToString for Point { + fn to_string(&self) -> String { + format!("({}, {})", self.row, self.col) + } +} + pub fn all_coords(width: usize, height: usize) -> impl Iterator { (0..height) .cartesian_product(0..width) @@ -69,3 +76,43 @@ pub fn flood(digraph: &[Vec>], start: Point) -> BTreeSet { reachable } + +//2d spatial dag +pub fn paths_to_each_point( + digraph: &[Vec>], + start: Point, +) -> Vec>>> { + let mut paths_to_each_point = vec![vec![BTreeSet::new(); digraph.len()]; digraph[0].len()]; + paths_to_each_point[start.row][start.col] = BTreeSet::from_iter([vec![start]]); + let mut frontier = BTreeSet::from_iter([start]); + + while let Some(cursor) = frontier.pop_first() { + println!("cursor is at ({}, {})", cursor.row, cursor.col); + for point in &digraph[cursor.row][cursor.col] { + println!("dealing with adjacent point ({}, {})", point.row, point.col); + frontier.insert(*point); + println!( + "frontier now has {} points: {}", + frontier.len(), + frontier.iter().map(|pt| pt.to_string()).join(", ") + ); + let paths_to_new_point = paths_to_each_point[cursor.row][cursor.col].clone(); + for mut path in paths_to_new_point { + path.push(*point); + paths_to_each_point[point.row][point.col].insert(path); + } + } + } + + dbg!(paths_to_each_point.len()); + paths_to_each_point +} + +pub fn print_grid(paths: Vec>) -> Vec> { + let s = paths + .iter() + .map(|row| row.iter().map(|count| count.to_string()).join("")) + .join("\n"); + println!("{s}\n"); + paths +}