1
1
use adventofcode2024:: ascii:: { Dir , Map , Pos } ;
2
2
use adventofcode2024:: input:: AocInput ;
3
3
use std:: cmp:: Ordering ;
4
- use std:: collections:: { BinaryHeap , HashSet } ;
4
+ use std:: collections:: { BinaryHeap , HashMap , HashSet } ;
5
5
use std:: time:: Instant ;
6
6
7
- #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
8
- struct State ( Pos , Dir , i64 ) ;
7
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
8
+ struct State ( Vec < Pos > , Dir , i64 ) ;
9
9
10
10
impl Ord for State {
11
11
fn cmp ( & self , other : & Self ) -> Ordering {
@@ -22,30 +22,66 @@ impl PartialOrd for State {
22
22
fn part1 ( map : & Map , start : Pos , end : Pos ) {
23
23
let mut work: BinaryHeap < State > = BinaryHeap :: new ( ) ;
24
24
let mut done: HashSet < ( Pos , Dir ) > = HashSet :: new ( ) ;
25
- work. push ( State ( start, Dir :: E , 0 ) ) ;
25
+ work. push ( State ( vec ! [ start] , Dir :: E , 0 ) ) ;
26
26
while let Some ( s) = work. pop ( ) {
27
- if done. contains ( & ( s. 0 , s. 1 ) ) {
27
+ let pos = * s. 0 . last ( ) . unwrap ( ) ;
28
+ let dir = s. 1 ;
29
+ if done. contains ( & ( pos, dir) ) {
28
30
continue ;
29
31
}
30
- if s. 0 == end {
32
+ done. insert ( ( pos, dir) ) ;
33
+ if pos == end {
31
34
println ! ( "Part 1: {:?}" , s. 2 ) ;
32
35
return ;
33
36
}
34
- work. push ( State ( s. 0 , s. 1 . right90 ( ) , s. 2 + 1000 ) ) ;
35
- work. push ( State ( s. 0 , s. 1 . left90 ( ) , s. 2 + 1000 ) ) ;
36
- let t = s. 0 . step ( s. 1 ) ;
37
- if map. get ( t) == '.' {
38
- work. push ( State ( t, s. 1 , s. 2 + 1 ) ) ;
37
+ work. push ( State ( s. 0 . clone ( ) , dir. right90 ( ) , s. 2 + 1000 ) ) ;
38
+ work. push ( State ( s. 0 . clone ( ) , dir. left90 ( ) , s. 2 + 1000 ) ) ;
39
+ let target = pos. step ( dir) ;
40
+ if map. get ( target) == '.' {
41
+ let mut extended_path = s. 0 . clone ( ) ;
42
+ extended_path. push ( target) ;
43
+ work. push ( State ( extended_path, dir, s. 2 + 1 ) ) ;
39
44
}
40
- done. insert ( ( s. 0 , s. 1 ) ) ;
41
45
}
42
46
panic ! ( "No path found!" ) ;
43
47
}
44
48
45
- fn part2 ( _map : & Map , start : Pos , end : Pos ) {
46
- println ! ( "Part 2: {}" , 2 ) ;
49
+
50
+ fn part2 ( map : & Map , start : Pos , end : Pos ) {
51
+ let mut work: BinaryHeap < State > = BinaryHeap :: new ( ) ;
52
+ let mut done: HashMap < ( Pos , Dir ) , i64 > = HashMap :: new ( ) ;
53
+ let mut best: Vec < State > = Vec :: new ( ) ;
54
+ work. push ( State ( vec ! [ start] , Dir :: E , 0 ) ) ;
55
+ while let Some ( s) = work. pop ( ) {
56
+ let pos = * s. 0 . last ( ) . unwrap ( ) ;
57
+ let dir = s. 1 ;
58
+ if let Some ( cc) = done. get ( & ( pos, dir) ) {
59
+ if * cc < s. 2 {
60
+ continue ;
61
+ }
62
+ }
63
+ done. insert ( ( pos, dir) , s. 2 ) ;
64
+ if pos == end {
65
+ if !best. is_empty ( ) && best. first ( ) . unwrap ( ) . 2 < s. 2 {
66
+ break ;
67
+ }
68
+ best. push ( s. clone ( ) ) ;
69
+ }
70
+ work. push ( State ( s. 0 . clone ( ) , dir. right90 ( ) , s. 2 + 1000 ) ) ;
71
+ work. push ( State ( s. 0 . clone ( ) , dir. left90 ( ) , s. 2 + 1000 ) ) ;
72
+ let target = pos. step ( dir) ;
73
+ if map. get ( target) == '.' {
74
+ let mut extended_path = s. 0 . clone ( ) ;
75
+ extended_path. push ( target) ;
76
+ work. push ( State ( extended_path, dir, s. 2 + 1 ) ) ;
77
+ }
78
+ }
79
+
80
+ let cnt: HashSet < Pos > = best. iter ( ) . map ( |s| s. 0 . clone ( ) ) . flatten ( ) . collect ( ) ;
81
+ println ! ( "Part 2: {:?}" , cnt. len( ) ) ;
47
82
}
48
83
84
+
49
85
fn main ( ) {
50
86
let start = Instant :: now ( ) ;
51
87
let mut input = AocInput :: new ( "inputs/day16.txt" ) ;
0 commit comments