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

Commit c5cf2a2

Browse files
committed
Add solution day 13 part 2
1 parent 4bf1858 commit c5cf2a2

File tree

3 files changed

+27
-59
lines changed

3 files changed

+27
-59
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,4 @@ automatically rebuilt and redeployed ever time the `common` module or their own
5757
| 10 | ⭐ ⭐ | 23 | |
5858
| 11 | ⭐ ⭐ | 24 | |
5959
| 12 | ⭐ ⭐ | 25 | |
60-
| 13 | | | |
60+
| 13 | | | |

solutions/day13/main.go

Lines changed: 16 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,74 +3,34 @@ package main
33
import (
44
"fmt"
55
"github.com/terminalnode/adventofcode2024/common"
6-
"log"
7-
"math"
86
)
97

10-
func main() {
11-
common.Setup(13, part1, nil)
12-
}
8+
func main() { common.Setup(13, part1, part2) }
9+
func part1(input string) string { return solve(input, false) }
10+
func part2(input string) string { return solve(input, true) }
1311

14-
func part1(
12+
func solve(
1513
input string,
14+
part2 bool,
1615
) string {
17-
problems, err := parseProblems(input)
16+
problems, err := parseProblems(input, part2)
1817
if err != nil {
1918
return fmt.Sprintf("Failed to parse input: %v", err)
2019
}
2120

2221
sum := int64(0)
2322
for _, p := range problems {
24-
minTokenCost := findMinTokenCost(p)
25-
if minTokenCost != -1 {
26-
sum += minTokenCost
27-
}
28-
}
29-
30-
return fmt.Sprintf("At least %d tokens to solve these %d claw machines", sum, len(problems))
31-
}
32-
33-
func findMinTokenCost(
34-
p problem,
35-
) int64 {
36-
smallest := int64(math.MaxInt64)
37-
38-
for timesA := int64(0); true; timesA++ {
39-
cX := timesA * p.aX
40-
cY := timesA * p.aY
41-
if cX > p.goalX || cY > p.goalY {
42-
break
43-
}
44-
45-
minMoves := findMinTokenCostAfterA(cX, cY, timesA, p)
46-
if minMoves != -1 && minMoves < smallest {
47-
log.Printf("New smallest! %d", minMoves)
48-
smallest = minMoves
49-
}
50-
}
51-
52-
if smallest == math.MaxInt64 {
53-
return -1
54-
}
55-
return smallest
56-
}
57-
58-
func findMinTokenCostAfterA(
59-
cX int64,
60-
cY int64,
61-
timesA int64,
62-
p problem,
63-
) int64 {
64-
for timesB := int64(0); true; timesB++ {
65-
newX := timesB*p.bX + cX
66-
newY := timesB*p.bY + cY
67-
68-
if newX > p.goalX || newY > p.goalY {
69-
break
70-
} else if newX == p.goalX && newY == p.goalY {
71-
return timesA*3 + timesB
23+
// Apparently this is an application of some Cramer's rule. ¯\_(ツ)_/¯
24+
det := p.aX*p.bY - p.aY*p.bX
25+
a := (p.goalX*p.bY - p.goalY*p.bX) / det
26+
b := (p.aX*p.goalY - p.aY*p.goalX) / det
27+
28+
x := a*p.aX + b*p.bX
29+
y := a*p.aY + b*p.bY
30+
if x == p.goalX && y == p.goalY {
31+
sum += 3*a + b
7232
}
7333
}
7434

75-
return -1
35+
return fmt.Sprintf("Cost is %d tokens to solve these %d claw machines", sum, len(problems))
7636
}

solutions/day13/parse.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ var r = regexp.MustCompile(`Button A: X\+(\d+), Y\+(\d+)\nButton B: X\+(\d+), Y\
2020

2121
func parseProblems(
2222
input string,
23+
part2 bool,
2324
) ([]problem, error) {
2425
matches := r.FindAllSubmatch([]byte(input), -1)
2526
problems := make([]problem, len(matches))
@@ -42,13 +43,20 @@ func parseProblems(
4243
digits[j] = d
4344
}
4445

46+
goalX := digits[4]
47+
goalY := digits[5]
48+
if part2 {
49+
goalX += 10000000000000
50+
goalY += 10000000000000
51+
}
52+
4553
problems[i] = problem{
4654
aX: digits[0],
4755
aY: digits[1],
4856
bX: digits[2],
4957
bY: digits[3],
50-
goalX: digits[4],
51-
goalY: digits[5],
58+
goalX: goalX,
59+
goalY: goalY,
5260
}
5361
}
5462

0 commit comments

Comments
 (0)