Skip to content
This repository was archived by the owner on Dec 28, 2024. It is now read-only.

Commit 93b7bbb

Browse files
committed
Add solution day 20 part 2
1 parent 3f1efe3 commit 93b7bbb

File tree

3 files changed

+34
-33
lines changed

3 files changed

+34
-33
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ automatically rebuilt and redeployed every time the `common` module or their own
5252
| 04 | ⭐ ⭐ | 17 | ⭐ ⭐ |
5353
| 05 | ⭐ ⭐ | 18 | ⭐ ⭐ |
5454
| 06 | ⭐ ⭐ | 19 | ⭐ ⭐ |
55-
| 07 | ⭐ ⭐ | 20 | |
55+
| 07 | ⭐ ⭐ | 20 | |
5656
| 08 | ⭐ ⭐ | 21 | |
5757
| 09 | ⭐ ⭐ | 22 | |
5858
| 10 | ⭐ ⭐ | 23 | |

common/util/math.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package util
2+
3+
func AbsInt(x int) int {
4+
if x < 0 {
5+
return -x
6+
}
7+
return x
8+
}

solutions/day20/main.go

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ import (
88
)
99

1010
func main() {
11-
common.Setup(20, part1, nil)
11+
common.Setup(20, part1, part2)
1212
}
1313

14-
func part1(
14+
func part1(input string) string { return solve(input, 2, 100) }
15+
func part2(input string) string { return solve(input, 20, 100) }
16+
17+
func solve(
1518
input string,
19+
steps int,
20+
limit int,
1621
) string {
1722
p, err := parse(input)
1823
if err != nil {
@@ -26,24 +31,25 @@ func part1(
2631

2732
cheatCounts := make(map[int]int)
2833
for _, pos := range path {
29-
for k, v := range findAllCheats(dm, pos, 2) {
34+
for k, v := range findAllCheats(dm, pos, p.e, steps) {
3035
cheatCounts[k] += v
3136
}
3237
}
3338

3439
count := 0
3540
for k, v := range cheatCounts {
36-
if k >= 100 {
41+
if k >= limit {
3742
count += v
3843
}
3944
}
4045

41-
return fmt.Sprintf("Number of cheats saving at least 100ps: %d", count)
46+
return fmt.Sprintf("Number of cheats saving at least %d ps: %d", limit, count)
4247
}
4348

4449
func findAllCheats(
4550
dm distanceMap,
4651
pos util.Coordinate,
52+
ePos util.Coordinate,
4753
steps int,
4854
) map[int]int {
4955
// Initialize visited set
@@ -53,36 +59,23 @@ func findAllCheats(
5359
}
5460

5561
cheats := make(map[int]int)
56-
positions := pos.Adjacent4()
5762
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
63+
for step := 2; step <= steps; step++ {
64+
for y := -step; y <= step; y++ {
65+
remainingSteps := step - util.AbsInt(y)
66+
for x := -remainingSteps; x <= remainingSteps; x++ {
67+
if util.AbsInt(x)+util.AbsInt(y) != step {
68+
continue
69+
}
70+
nPos := util.Coordinate{X: pos.X + x, Y: pos.Y + y}
71+
72+
nDistance := dm[nPos.Y][nPos.X]
73+
saved := distance - nDistance - step
74+
if (nDistance != 0 || nPos.Equals(ePos)) && saved > 0 {
75+
cheats[saved] += 1
76+
}
6477
}
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()...)
8378
}
84-
85-
positions = newPositions
8679
}
8780

8881
return cheats

0 commit comments

Comments
 (0)