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

Commit 407c87f

Browse files
committed
Add solution day 15 part 2
1 parent 9aa7b41 commit 407c87f

File tree

2 files changed

+87
-27
lines changed

2 files changed

+87
-27
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ automatically rebuilt and redeployed ever time the `common` module or their own
4646
| Day | Solution | Day | Solution |
4747
|-----|----------|-----|----------|
4848
| 01 | ⭐ ⭐ | 14 | ⭐ ⭐ |
49-
| 02 | ⭐ ⭐ | 15 | |
49+
| 02 | ⭐ ⭐ | 15 | |
5050
| 03 | ⭐ ⭐ | 16 | |
5151
| 04 | ⭐ ⭐ | 17 | |
5252
| 05 | ⭐ ⭐ | 18 | |

solutions/day15/main.go

Lines changed: 86 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,118 @@
11
package main
22

33
import (
4+
"errors"
45
"fmt"
56
"github.com/terminalnode/adventofcode2024/common"
67
"github.com/terminalnode/adventofcode2024/common/util"
78
)
89

9-
func main() {
10-
common.Setup(15, part1, nil)
11-
}
10+
func main() { common.Setup(15, part1, part2) }
11+
func part1(input string) string { return solve(input, false) }
12+
func part2(input string) string { return solve(input, true) }
13+
14+
type visitedSet = map[int]map[int]bool
1215

13-
func part1(
16+
func solve(
1417
input string,
18+
makeWide bool,
1519
) string {
16-
p, err := parse(input, false)
20+
p, err := parse(input, makeWide)
1721
if err != nil {
1822
return fmt.Sprintf("Failed to parse input: %v", err)
1923
}
2024

2125
for _, move := range p.moves {
22-
endPosition, err := findEndPosition(p.warehouse, p.robot, move)
26+
newPos := move(p.robot)
27+
boxMoves, err := getBoxMoves(p.warehouse, newPos, move, make(visitedSet))
2328
if err != nil {
2429
continue
2530
}
2631

27-
newRobot := move(p.robot)
28-
if !newRobot.Equals(endPosition) {
29-
// End position is more than one step, meaning we need to move boxes
30-
p.warehouse[newRobot.Y][newRobot.X] = Ground
31-
p.warehouse[endPosition.Y][endPosition.X] = Box
32+
// Zero out all moves
33+
for _, bm := range boxMoves {
34+
c := bm.curr
35+
p.warehouse[c.Y][c.X] = Ground
36+
}
37+
38+
// Put all boxes in their new positions
39+
for _, bm := range boxMoves {
40+
c := bm.new
41+
p.warehouse[c.Y][c.X] = bm.ch
3242
}
33-
p.robot = newRobot
43+
44+
p.robot = newPos
3445
}
3546

47+
if makeWide {
48+
return fmt.Sprintf("Sum of all GPS coordinates in the wide area: %d", score(p.warehouse))
49+
}
3650
return fmt.Sprintf("Sum of all GPS coordinates: %d", score(p.warehouse))
3751
}
3852

39-
func findEndPosition(
53+
type boxMove struct {
54+
ch int32
55+
curr util.Coordinate
56+
new util.Coordinate
57+
}
58+
59+
func getBoxMoves(
4060
w warehouseMatrix,
41-
s util.Coordinate,
61+
start util.Coordinate,
4262
d util.Direction,
43-
) (util.Coordinate, error) {
44-
np := d(s)
45-
ch := w[np.Y][np.X]
46-
switch ch {
47-
case Ground:
48-
return np, nil
49-
case Box:
50-
return findEndPosition(w, np, d)
51-
case Wall:
52-
return np, fmt.Errorf("wall hit")
63+
set visitedSet,
64+
) ([]boxMove, error) {
65+
if inVisitedSet(set, start) {
66+
return []boxMove{}, nil
67+
}
68+
set[start.X][start.Y] = true
69+
70+
// Initializations, boxMoves capacity is just a guess
71+
boxMoves := make([]boxMove, 0, 200)
72+
ch := w[start.Y][start.X]
73+
74+
// Early returns on ground and wall
75+
if ch == Ground {
76+
return boxMoves, nil
77+
} else if ch == Wall {
78+
return boxMoves, errors.New("wall hit")
5379
}
5480

55-
panic(fmt.Sprintf("Invalid character: %c", ch))
81+
// Whatever happens, add this move to the list
82+
newPos := d(start)
83+
boxMoves = append(boxMoves, boxMove{ch: ch, curr: start, new: newPos})
84+
85+
// Get next moves and add to the list
86+
next, err := getBoxMoves(w, newPos, d, set)
87+
if err != nil {
88+
return boxMoves, err
89+
}
90+
boxMoves = append(boxMoves, next...)
91+
92+
// Now do the same thing for the partner boxes, if any
93+
if ch != Box {
94+
if ch == LeftBox {
95+
next, err = getBoxMoves(w, start.East(), d, set)
96+
} else if ch == RightBox {
97+
next, err = getBoxMoves(w, start.West(), d, set)
98+
}
99+
if err != nil {
100+
return boxMoves, err
101+
}
102+
boxMoves = append(boxMoves, next...)
103+
}
104+
105+
return boxMoves, err
106+
}
107+
108+
func inVisitedSet(
109+
set visitedSet,
110+
c util.Coordinate,
111+
) bool {
112+
if set[c.X] == nil {
113+
set[c.X] = make(map[int]bool)
114+
}
115+
return set[c.X][c.Y]
56116
}
57117

58118
func score(
@@ -61,7 +121,7 @@ func score(
61121
sum := 0
62122
for y, row := range wh {
63123
for x, ch := range row {
64-
if ch != Box {
124+
if ch != Box && ch != LeftBox {
65125
continue
66126
}
67127
sum += x + 100*y

0 commit comments

Comments
 (0)