@@ -26,22 +26,8 @@ func part1(
26
26
27
27
cheatCounts := make (map [int ]int )
28
28
for _ , pos := range path {
29
- distance := dm [pos.Y ][pos.X ]
30
- next := []util.Coordinate {
31
- pos .North ().North (),
32
- pos .South ().South (),
33
- pos .East ().East (),
34
- pos .West ().West (),
35
- }
36
-
37
- for _ , nPos := range next {
38
- // Normally moving two steps should give us two less distance,
39
- // so these 2 are subtracted from the saved amount.
40
- nDistance := dm [nPos.Y ][nPos.X ]
41
- saved := nDistance - distance - 2
42
- if saved > 0 {
43
- cheatCounts [saved ] += 1
44
- }
29
+ for k , v := range findAllCheats (dm , pos , 2 ) {
30
+ cheatCounts [k ] += v
45
31
}
46
32
}
47
33
@@ -50,12 +36,58 @@ func part1(
50
36
if k >= 100 {
51
37
count += v
52
38
}
53
- fmt .Printf ("There are %d cheats that save %d picoseconds.\n " , v , k )
54
39
}
55
40
56
41
return fmt .Sprintf ("Number of cheats saving at least 100ps: %d" , count )
57
42
}
58
43
44
+ func findAllCheats (
45
+ dm distanceMap ,
46
+ pos util.Coordinate ,
47
+ steps int ,
48
+ ) map [int ]int {
49
+ // Initialize visited set
50
+ visited := make (map [intY ]map [intX ]bool )
51
+ for y := range dm {
52
+ visited [y ] = make (map [intX ]bool )
53
+ }
54
+
55
+ cheats := make (map [int ]int )
56
+ positions := pos .Adjacent4 ()
57
+ distance := dm [pos.Y ][pos.X ]
58
+ for step := 1 ; step <= steps ; step ++ {
59
+ newPositions := make ([]util.Coordinate , 0 , 4 * len (positions ))
60
+ for _ , p := range positions {
61
+ // 1. Check if in visited set, if it is then skip.
62
+ if visited [p.Y ][p.X ] || visited [p .Y ] == nil {
63
+ continue
64
+ }
65
+ visited [p.Y ][p.X ] = true
66
+
67
+ // 2. Calculate time saved
68
+ // Moving here normally will take $step number of steps, so savings
69
+ // are calculated by subtracting step from the distance map.
70
+ nDistance := dm [p.Y ][p.X ]
71
+ saved := nDistance - distance - step
72
+
73
+ if nDistance != 0 && saved <= 0 {
74
+ // 3. If we didn't save time by going this way, continue.
75
+ continue
76
+ } else if nDistance != 0 {
77
+ // 4. We didn't save time by going here, but we're still in the wilderness
78
+ cheats [saved ] += 1
79
+ }
80
+
81
+ // 5. This position is not trash, lets add all it's neighbors to the new positions set
82
+ newPositions = append (newPositions , p .Adjacent4 ()... )
83
+ }
84
+
85
+ positions = newPositions
86
+ }
87
+
88
+ return cheats
89
+ }
90
+
59
91
func (p parsedInput ) createDistanceMap () (distanceMap , []util.Coordinate , error ) {
60
92
newM := make (distanceMap )
61
93
path := make ([]util.Coordinate , 0 , p .length )
0 commit comments