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

Commit e100721

Browse files
committed
Add solution day 21 part 1
1 parent 0e9ea6f commit e100721

File tree

3 files changed

+146
-2
lines changed

3 files changed

+146
-2
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ automatically rebuilt and redeployed every time the `common` module or their own
5353
| 05 | ⭐ ⭐ | 18 | ⭐ ⭐ |
5454
| 06 | ⭐ ⭐ | 19 | ⭐ ⭐ |
5555
| 07 | ⭐ ⭐ | 20 | ⭐ ⭐ |
56-
| 08 | ⭐ ⭐ | 21 | |
56+
| 08 | ⭐ ⭐ | 21 | |
5757
| 09 | ⭐ ⭐ | 22 | ⭐ ⭐ |
5858
| 10 | ⭐ ⭐ | 23 | ⭐ ⭐ |
5959
| 11 | ⭐ ⭐ | 24 | ⭐ ⭐ |

solutions/day21/keypad.go

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package main
2+
3+
import (
4+
"github.com/terminalnode/adventofcode2024/common/util"
5+
)
6+
7+
var numStart = util.Coordinate{X: 2, Y: 3}
8+
var dirStart = util.Coordinate{X: 2, Y: 0}
9+
10+
// Char to Pos on numeric keypad
11+
func charToPosNum(
12+
c int,
13+
) util.Coordinate {
14+
switch c {
15+
case '0':
16+
return util.Coordinate{X: 1, Y: 3}
17+
case 'A':
18+
return numStart
19+
default:
20+
y := 2 - ((c - '0' - 1) / 3)
21+
x := (c - '0' - 1) % 3
22+
return util.Coordinate{X: int(x), Y: int(y)}
23+
}
24+
}
25+
26+
// Char to Pos on directional keypad
27+
func charToPosDir(
28+
c int,
29+
) util.Coordinate {
30+
switch c {
31+
case '^':
32+
return util.Coordinate{X: 1, Y: 0}
33+
case '<':
34+
return util.Coordinate{X: 0, Y: 1}
35+
case 'v':
36+
return util.Coordinate{X: 1, Y: 1}
37+
case '>':
38+
return util.Coordinate{X: 2, Y: 1}
39+
default:
40+
return util.Coordinate{X: 2, Y: 0}
41+
}
42+
}
43+
44+
func shortestPath(
45+
start, end util.Coordinate,
46+
useNumPad bool,
47+
) []int {
48+
var path []int
49+
dx := end.X - start.X
50+
dy := end.Y - start.Y
51+
pVert, pHor := buildPath(dx, dy)
52+
53+
left := end.X < start.X
54+
var gap bool
55+
if useNumPad {
56+
gap = (start.Y == 3 && end.X == 0) || (start.X == 0 && end.Y == 3)
57+
} else {
58+
gap = (start.X == 0 && end.Y == 0) || (start.Y == 0 && end.X == 0)
59+
}
60+
61+
// The gap is on the left side in both pads, so if we're moving left and would cross
62+
// the gap we have to avoid it. If not, apparently it's always best to move vertical first.
63+
if left != gap {
64+
path = append(path, pHor...)
65+
path = append(path, pVert...)
66+
} else {
67+
path = append(path, pVert...)
68+
path = append(path, pHor...)
69+
}
70+
path = append(path, 'A')
71+
return path
72+
}
73+
74+
func buildPath(
75+
dx int,
76+
dy int,
77+
) ([]int, []int) {
78+
adx := util.AbsInt(dx)
79+
ady := util.AbsInt(dy)
80+
pVert := make([]int, ady)
81+
pHor := make([]int, adx)
82+
83+
for i := range adx {
84+
if dx < 0 {
85+
pHor[i] = '<'
86+
} else {
87+
pHor[i] = '>'
88+
}
89+
}
90+
91+
for i := range ady {
92+
if dy < 0 {
93+
pVert[i] = '^'
94+
} else {
95+
pVert[i] = 'v'
96+
}
97+
}
98+
99+
return pVert, pHor
100+
}

solutions/day21/main.go

+45-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,53 @@
11
package main
22

33
import (
4+
"fmt"
45
"github.com/terminalnode/adventofcode2024/common"
6+
"strconv"
7+
"strings"
58
)
69

710
func main() {
8-
common.Setup(21, nil, nil)
11+
common.Setup(21, part1, nil)
12+
}
13+
14+
func part1(
15+
input string,
16+
) string {
17+
var out string
18+
19+
sequences := strings.Split(input, "\n")
20+
sum := 0
21+
for _, code := range sequences {
22+
// Five is the longest path between two keys on numeric pad
23+
path := make([]int, 0, 5*len(code))
24+
prev := numStart
25+
for _, c := range code {
26+
curr := charToPosNum(int(c))
27+
path = append(path, shortestPath(prev, curr, true)...)
28+
prev = curr
29+
}
30+
31+
for range 2 {
32+
// Three is the longest path between two keys on directional pad
33+
newPath := make([]int, 0, 3*len(path))
34+
prev = dirStart
35+
for _, c := range path {
36+
curr := charToPosDir(c)
37+
newPath = append(newPath, shortestPath(prev, curr, false)...)
38+
prev = curr
39+
}
40+
path = newPath
41+
}
42+
43+
codeNumeric, err := strconv.Atoi(code[:len(code)-1])
44+
if err != nil {
45+
return fmt.Sprintf("Failed to parse code %s as int: %v", code, err)
46+
}
47+
48+
sum += len(path) * codeNumeric
49+
}
50+
51+
out += fmt.Sprintf("Sum: %d", sum)
52+
return out
953
}

0 commit comments

Comments
 (0)