|
3 | 3 |
|
4 | 4 | use std::{fs, io}; |
5 | 5 | use std::collections::{BTreeMap, BTreeSet}; |
| 6 | +use std::hash::{DefaultHasher, Hash, Hasher}; |
6 | 7 | use std::path::Path; |
7 | 8 | use lib::vector::Vector; |
8 | 9 |
|
@@ -73,28 +74,36 @@ fn part2(input: &Input) -> usize { |
73 | 74 | fn rating(trailhead: Vec2, heights: &BTreeMap<Vec2, u8>) -> usize { |
74 | 75 | let mut rating = 0; |
75 | 76 |
|
76 | | - let mut visited: BTreeSet<Vec<Vec2>> = [vec![trailhead]].into_iter().collect(); |
77 | | - let mut edge = vec![vec![trailhead]]; |
| 77 | + let mut hasher = DefaultHasher::new(); |
| 78 | + trailhead.hash(&mut hasher); |
| 79 | + let hash = hasher.finish(); |
78 | 80 |
|
79 | | - while let Some(trail) = edge.pop() { |
80 | | - let pos = *trail.last().unwrap(); |
| 81 | + let mut visited: BTreeSet<u64> = [hash].into_iter().collect(); |
| 82 | + let mut edge = vec![(trailhead, hasher)]; |
| 83 | + |
| 84 | + while let Some((pos, hasher)) = edge.pop() { |
81 | 85 | let height = heights[&pos]; |
| 86 | + |
82 | 87 | if height == 9 { |
83 | 88 | rating += 1; |
84 | 89 | continue; |
85 | 90 | } |
86 | 91 |
|
87 | 92 | for dir in [UP, DOWN, LEFT, RIGHT] { |
88 | 93 | let next_pos = pos + dir; |
89 | | - let new_trail: Vec<_> = trail.iter().copied().chain([next_pos]).collect(); |
90 | 94 |
|
91 | | - if visited.contains(&new_trail) { |
| 95 | + let mut hasher = hasher.clone(); |
| 96 | + next_pos.hash(&mut hasher); |
| 97 | + let hash = hasher.finish(); |
| 98 | + |
| 99 | + if visited.contains(&hash) { |
92 | 100 | continue; |
93 | 101 | } |
94 | 102 |
|
| 103 | + visited.insert(hash); |
| 104 | + |
95 | 105 | if heights.get(&next_pos).copied() == Some(height + 1) { |
96 | | - visited.insert(new_trail.clone()); |
97 | | - edge.push(new_trail); |
| 106 | + edge.push((next_pos, hasher)); |
98 | 107 | } |
99 | 108 | } |
100 | 109 | } |
|
0 commit comments