-use std::collections::{HashSet, VecDeque};
+use std::collections::HashSet;
use std::ops::{Add, Index, Sub};
fn input() -> &'static str {
}
}
-fn parse(input: &str) -> Map {
- Map(input
- .lines()
- .map(|l| l.chars().map(|c| c.to_string().parse().unwrap()).collect())
- .collect())
-}
-
-fn find_height(map: &Map, height: u8) -> impl Iterator<Item = Point> + use<'_> {
- map.0.iter().zip(0..).flat_map(move |(v, i)| {
- v.iter()
- .zip(0..)
- .filter(move |(&c, _)| c == height)
- .map(move |(_, j)| Point(i, j))
- })
-}
+impl Map {
+ fn find_height(&self, height: u8) -> impl Iterator<Item = Point> + use<'_> {
+ self.0.iter().zip(0..).flat_map(move |(v, i)| {
+ v.iter()
+ .zip(0..)
+ .filter(move |(&c, _)| c == height)
+ .map(move |(_, j)| Point(i, j))
+ })
+ }
-fn walk_paths(map: &Map, root: &Point) -> Vec<Point> {
- let bound = map.0.len();
- let mut adjits = VecDeque::from([root.adjacent(bound)]);
- let mut adjs: Vec<Point> = vec![];
- for n in 1..=9 {
- while let Some(adj) = adjits.pop_front() {
- adjs.extend(adj);
- }
- if n < 9 {
- while let Some(p) = adjs.pop() {
- if map[p] == n {
- adjits.push_back(p.adjacent(bound))
+ fn walk_paths(&self, root: &Point) -> Vec<Point> {
+ let bound = self.0.len();
+ let mut iterators = vec![];
+ let mut points = vec![*root];
+ for n in 0..9 {
+ iterators.extend(points.drain(..).filter_map(|p| {
+ if self[p] == n {
+ Some(p.adjacent(bound))
+ } else {
+ None
}
- }
+ }));
+ points.extend(iterators.drain(..).flatten());
}
+ points.into_iter().filter(|&p| self[p] == 9).collect()
+ }
+
+ fn count_reachable_heights(&self, root: &Point) -> u64 {
+ self.walk_paths(root)
+ .into_iter()
+ .collect::<HashSet<_>>()
+ .len()
+ .try_into()
+ .unwrap()
}
- adjs.iter().filter(|&&p| map[p] == 9).copied().collect()
-}
-fn count_trails(map: &Map, root: &Point) -> u64 {
- walk_paths(map, root)
- .iter()
- .collect::<HashSet<_>>()
- .len()
- .try_into()
- .unwrap()
+ fn count_unique_trails(&self, root: &Point) -> u64 {
+ self.walk_paths(root).len().try_into().unwrap()
+ }
}
-fn count_unique_trails(map: &Map, root: &Point) -> u64 {
- walk_paths(map, root).len().try_into().unwrap()
+fn parse(input: &str) -> Map {
+ Map(input
+ .lines()
+ .map(|l| l.chars().map(|c| c.to_string().parse().unwrap()).collect())
+ .collect())
}
pub fn part1() {
let map = parse(input());
- let n: u64 = find_height(&map, 0).map(|p| count_trails(&map, &p)).sum();
+ let n: u64 = map
+ .find_height(0)
+ .map(|p| map.count_reachable_heights(&p))
+ .sum();
println!("Day 10 Part 1: {}", n);
}
pub fn part2() {
let map = parse(input());
- let n: u64 = find_height(&map, 0)
- .map(|p| count_unique_trails(&map, &p))
+ let n: u64 = map
+ .find_height(0)
+ .map(|p| map.count_unique_trails(&p))
.sum();
println!("Day 10 Part 2: {}", n);
}
#[test]
fn test_count_trails() {
let map = parse(TINY_INPUT);
- assert_eq!(count_trails(&map, &Point(0, 0)), 1);
+ assert_eq!(map.count_reachable_heights(&Point(0, 0)), 1);
let map = parse(INPUT_STR);
- assert_eq!(count_trails(&map, &Point(0, 2)), 5);
- assert_eq!(count_trails(&map, &Point(0, 4)), 6);
- assert_eq!(count_trails(&map, &Point(2, 4)), 5);
- assert_eq!(count_trails(&map, &Point(4, 6)), 3);
- assert_eq!(count_trails(&map, &Point(5, 2)), 1);
- assert_eq!(count_trails(&map, &Point(5, 5)), 3);
- assert_eq!(count_trails(&map, &Point(6, 0)), 5);
- assert_eq!(count_trails(&map, &Point(6, 6)), 3);
- assert_eq!(count_trails(&map, &Point(7, 1)), 5);
+ assert_eq!(map.count_reachable_heights(&Point(0, 2)), 5);
+ assert_eq!(map.count_reachable_heights(&Point(0, 4)), 6);
+ assert_eq!(map.count_reachable_heights(&Point(2, 4)), 5);
+ assert_eq!(map.count_reachable_heights(&Point(4, 6)), 3);
+ assert_eq!(map.count_reachable_heights(&Point(5, 2)), 1);
+ assert_eq!(map.count_reachable_heights(&Point(5, 5)), 3);
+ assert_eq!(map.count_reachable_heights(&Point(6, 0)), 5);
+ assert_eq!(map.count_reachable_heights(&Point(6, 6)), 3);
+ assert_eq!(map.count_reachable_heights(&Point(7, 1)), 5);
}
#[test]
fn test_count_unique_trails() {
let map = parse(TINY_INPUT);
- assert_eq!(count_unique_trails(&map, &Point(0, 0)), 16);
+ assert_eq!(map.count_unique_trails(&Point(0, 0)), 16);
let map = parse(INPUT_STR);
- assert_eq!(count_unique_trails(&map, &Point(0, 2)), 20);
- assert_eq!(count_unique_trails(&map, &Point(0, 4)), 24);
- assert_eq!(count_unique_trails(&map, &Point(2, 4)), 10);
- assert_eq!(count_unique_trails(&map, &Point(4, 6)), 4);
- assert_eq!(count_unique_trails(&map, &Point(5, 2)), 1);
- assert_eq!(count_unique_trails(&map, &Point(5, 5)), 4);
- assert_eq!(count_unique_trails(&map, &Point(6, 0)), 5);
- assert_eq!(count_unique_trails(&map, &Point(6, 6)), 8);
- assert_eq!(count_unique_trails(&map, &Point(7, 1)), 5);
+ assert_eq!(map.count_unique_trails(&Point(0, 2)), 20);
+ assert_eq!(map.count_unique_trails(&Point(0, 4)), 24);
+ assert_eq!(map.count_unique_trails(&Point(2, 4)), 10);
+ assert_eq!(map.count_unique_trails(&Point(4, 6)), 4);
+ assert_eq!(map.count_unique_trails(&Point(5, 2)), 1);
+ assert_eq!(map.count_unique_trails(&Point(5, 5)), 4);
+ assert_eq!(map.count_unique_trails(&Point(6, 0)), 5);
+ assert_eq!(map.count_unique_trails(&Point(6, 6)), 8);
+ assert_eq!(map.count_unique_trails(&Point(7, 1)), 5);
}
}