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

Commit 5817dbe

Browse files
committed
Add solution day 18 part 2
1 parent ca5d2a8 commit 5817dbe

File tree

2 files changed

+77
-40
lines changed

2 files changed

+77
-40
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ automatically rebuilt and redeployed every time the `common` module or their own
5050
| 02 | ⭐ ⭐ | 15 | ⭐ ⭐ |
5151
| 03 | ⭐ ⭐ | 16 | ⭐ 🥸 |
5252
| 04 | ⭐ ⭐ | 17 ||
53-
| 05 | ⭐ ⭐ | 18 | |
53+
| 05 | ⭐ ⭐ | 18 | |
5454
| 06 | ⭐ ⭐ | 19 | |
5555
| 07 | ⭐ ⭐ | 20 | |
5656
| 08 | ⭐ ⭐ | 21 | |

solutions/day18/main.go

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

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

1313
func part1(
1414
input string,
1515
) string {
16-
out, err := run(input, 70, 70, 1024)
16+
m := buildMatrix()
17+
cs, err := parse(input)
1718
if err != nil {
18-
return err.Error()
19+
return fmt.Sprintf("Failed to parse input: %v", err)
1920
}
20-
return fmt.Sprintf("Shortest path is %d steps", out)
21+
22+
for _, c := range cs[:1024] {
23+
m[c.Y][c.X] = true
24+
}
25+
26+
start := util.Coordinate{X: 0, Y: 0}
27+
end := util.Coordinate{X: 70, Y: 70}
28+
visitedSet := buildVisitedSet[int]()
29+
shortestPath(m, start, end, 0, visitedSet)
30+
31+
shortest := visitedSet[70][70]
32+
return fmt.Sprintf("Shortest path is %d steps", shortest)
2133
}
2234

23-
func run(
35+
func part2(
2436
input string,
25-
maxX int,
26-
maxY int,
27-
fallenBytes int,
28-
) (int, error) {
29-
m := buildMatrix(maxX, maxY)
37+
) string {
38+
m := buildMatrix()
3039
cs, err := parse(input)
3140
if err != nil {
32-
return -1, err
41+
return fmt.Sprintf("Failed to parse input: %v", err)
3342
}
3443

35-
if len(cs) > fallenBytes {
36-
cs = cs[:fallenBytes]
37-
}
44+
// Initialize everything
45+
latest := cs[0]
46+
cs = cs[1:]
47+
winningSet := buildVisitedSet[bool]()
48+
m[latest.Y][latest.X] = true
49+
count := 1
50+
start := util.Coordinate{X: 0, Y: 0}
51+
end := util.Coordinate{X: 70, Y: 70}
52+
success := anyPath(m, start, end, buildVisitedSet[bool](), winningSet)
3853

39-
for _, c := range cs {
40-
m[c.Y][c.X] = true
41-
}
54+
for success && len(cs) > 0 {
55+
for !winningSet[latest.Y][latest.X] && len(cs) > 0 {
56+
count++
57+
latest = cs[0]
58+
cs = cs[1:]
59+
m[latest.Y][latest.X] = true
60+
}
4261

43-
visitedSet := buildVisitedSet(maxY)
44-
shortestPath(
45-
m,
46-
util.Coordinate{X: 0, Y: 0},
47-
util.Coordinate{X: maxX, Y: maxY},
48-
0,
49-
visitedSet,
50-
)
62+
winningSet = buildVisitedSet[bool]()
63+
success = anyPath(m, start, end, buildVisitedSet[bool](), winningSet)
64+
}
5165

52-
return visitedSet[maxY][maxX], nil
66+
return fmt.Sprintf("The byte that broke the camel's back was %s", latest)
5367
}
5468

55-
func buildMatrix(
56-
maxX int,
57-
maxY int,
58-
) [][]bool {
59-
out := make([][]bool, maxY+1)
60-
for y := 0; y <= maxY; y++ {
61-
out[y] = make([]bool, maxX+1)
69+
func buildMatrix() [][]bool {
70+
out := make([][]bool, 71)
71+
for y := 0; y <= 70; y++ {
72+
out[y] = make([]bool, 71)
6273
}
6374
return out
6475
}
6576

66-
func buildVisitedSet(
67-
maxY int,
68-
) map[int]map[int]int {
69-
visitedSet := make(map[int]map[int]int)
70-
for y := 0; y <= maxY; y++ {
71-
visitedSet[y] = make(map[int]int)
77+
func buildVisitedSet[T any]() map[int]map[int]T {
78+
visitedSet := make(map[int]map[int]T)
79+
for y := 0; y <= 70; y++ {
80+
visitedSet[y] = make(map[int]T)
7281
}
7382
return visitedSet
7483
}
@@ -106,3 +115,31 @@ func shortestPath(
106115
shortestPath(m, c.South(), goal, steps+1, visitedSet)
107116
shortestPath(m, c.West(), goal, steps+1, visitedSet)
108117
}
118+
119+
func anyPath(
120+
m [][]bool,
121+
c util.Coordinate,
122+
goal util.Coordinate,
123+
visitedSet map[int]map[int]bool,
124+
winningSet map[int]map[int]bool,
125+
) bool {
126+
if visitedSet[c.Y][c.X] || !util.In2DArray(c, m) || m[c.Y][c.X] {
127+
// Been here, outside matrix or position is impassable
128+
return false
129+
} else if c.Equals(goal) {
130+
// We did it!
131+
winningSet[c.Y][c.X] = true
132+
return true
133+
}
134+
135+
visitedSet[c.Y][c.X] = true
136+
winner := anyPath(m, c.South(), goal, visitedSet, winningSet) ||
137+
anyPath(m, c.East(), goal, visitedSet, winningSet) ||
138+
anyPath(m, c.West(), goal, visitedSet, winningSet) ||
139+
anyPath(m, c.North(), goal, visitedSet, winningSet)
140+
if winner {
141+
winningSet[c.Y][c.X] = true
142+
}
143+
144+
return winner
145+
}

0 commit comments

Comments
 (0)