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

Commit d19b692

Browse files
committed
Add solution day 16 part 2
1 parent 7f48f69 commit d19b692

File tree

3 files changed

+74
-21
lines changed

3 files changed

+74
-21
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,14 @@ automatically rebuilt and redeployed every time the `common` module or their own
4141

4242
## Progress
4343
* ⭐ means solved
44-
* 🥸 means solved, but takes over a minute to run, or requires some manual tinkering
44+
* 🥸 means solved, but takes 10 seconds or more to run
45+
* 💩 means solved, but takes over a minute to run
4546

4647
| Day | Solution | Day | Solution |
4748
|-----|----------|-----|----------|
4849
| 01 | ⭐ ⭐ | 14 | ⭐ ⭐ |
4950
| 02 | ⭐ ⭐ | 15 | ⭐ ⭐ |
50-
| 03 | ⭐ ⭐ | 16 | |
51+
| 03 | ⭐ ⭐ | 16 |🥸 |
5152
| 04 | ⭐ ⭐ | 17 | |
5253
| 05 | ⭐ ⭐ | 18 | |
5354
| 06 | ⭐ ⭐ | 19 | |

solutions/day16/main.go

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
)
88

99
func main() {
10-
common.Setup(16, part1, nil)
10+
common.Setup(16, part1, part2)
1111
}
1212

1313
func part1(
@@ -20,50 +20,84 @@ func part1(
2020

2121
// Initialize visited set with end point
2222
set := initializeVisitedSet(i)
23-
loop(initialReindeer(i.s), i, set)
23+
loop(initialReindeer(i.s), i, set, initializeWinningSet(i), -1)
2424

2525
return fmt.Sprintf("Cheapest path: %v", lowestSoFar(i, set))
2626
}
2727

28+
func part2(
29+
input string,
30+
) string {
31+
i, err := parse(input)
32+
if err != nil {
33+
return fmt.Sprintf("Failed to parse input: %v", err)
34+
}
35+
36+
// Initialize visited set with end point
37+
visited := initializeVisitedSet(i)
38+
loop(initialReindeer(i.s), i, visited, initializeWinningSet(i), -1)
39+
40+
// Run again with the correct answer, which should weed out
41+
// all paths that were the best before better paths were found.
42+
winners := initializeWinningSet(i)
43+
answer := lowestSoFar(i, visited)
44+
loop(initialReindeer(i.s), i, initializeVisitedSet(i), winners, answer)
45+
winners[i.e.Y][i.e.X] = true
46+
47+
count := 0
48+
for _, ys := range winners {
49+
count += len(ys)
50+
}
51+
52+
return fmt.Sprintf("Best seats: %d", count)
53+
}
54+
2855
func loop(
2956
r reindeer,
3057
i parsedInput,
3158
set visitedSet,
32-
) {
33-
if r.visitAndCheckIfDead(set) {
34-
return
59+
winners winningSet,
60+
answer int,
61+
) bool {
62+
isWinner := false
63+
if r.visitAndCheckIfDead(set, answer != -1) {
64+
return false
3565
}
3666

3767
lowest := lowestSoFar(i, set)
38-
if lowest != 0 && r.score > lowest {
39-
return
68+
if answer == -1 && lowest != 0 && r.score > lowest {
69+
winners[r.p.Y][r.p.X] = true
70+
return false
4071
}
4172

4273
if r.p.Equals(i.e) {
43-
return
74+
if answer == -1 {
75+
return true
76+
} else {
77+
return r.score == answer
78+
}
4479
}
4580

4681
newR, err := r.forward(i.m)
47-
if err == nil {
48-
loop(newR, i, set)
82+
if err == nil && loop(newR, i, set, winners, answer) {
83+
isWinner = true
4984
}
5085

5186
newR, err = r.turnClockwise().forward(i.m)
52-
if err == nil {
53-
loop(newR, i, set)
87+
if err == nil && loop(newR, i, set, winners, answer) {
88+
isWinner = true
5489
}
5590

56-
newR, err = r.turnClockwise().turnClockwise().forward(i.m)
57-
if err == nil {
58-
loop(newR, i, set)
91+
newR, err = r.turnCounterClockwise().forward(i.m)
92+
if err == nil && loop(newR, i, set, winners, answer) {
93+
isWinner = true
5994
}
6095

61-
newR, err = r.turnCounterClockwise().forward(i.m)
62-
if err == nil {
63-
loop(newR, i, set)
96+
if isWinner {
97+
winners[r.p.Y][r.p.X] = true
6498
}
6599

66-
return
100+
return isWinner
67101
}
68102

69103
func lowestSoFar(
@@ -85,3 +119,13 @@ func initializeVisitedSet(
85119
}
86120
return set
87121
}
122+
123+
func initializeWinningSet(
124+
i parsedInput,
125+
) winningSet {
126+
set := make(winningSet)
127+
for y, _ := range i.m {
128+
set[y] = make(map[intX]bool)
129+
}
130+
return set
131+
}

solutions/day16/reindeer.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ type intY = int
1010
type intDirection = int
1111
type intScore = int
1212
type visitedSet = map[intY]map[intX]intScore
13+
type winningSet = map[intY]map[intX]bool
1314

1415
const (
1516
North = iota
@@ -78,12 +79,19 @@ func (r reindeer) turnCounterClockwise() reindeer {
7879

7980
func (r reindeer) visitAndCheckIfDead(
8081
set visitedSet,
82+
leeway bool,
8183
) bool {
8284
v := set[r.p.Y][r.p.X]
8385
if v == 0 || r.score < v {
8486
set[r.p.Y][r.p.X] = r.score
8587
return false
8688
}
89+
90+
// This leeway allows to find "temporarily suboptimal paths" when doing part 2
91+
if leeway && r.score < (v+2000) {
92+
return false
93+
}
94+
8795
return true
8896
}
8997

0 commit comments

Comments
 (0)