Skip to content

Commit 9ff25d3

Browse files
committed
Add solution for Y2024D13.
1 parent d060d3f commit 9ff25d3

File tree

6 files changed

+85
-1
lines changed

6 files changed

+85
-1
lines changed

Diff for: README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ _"Anything that's worth doing, is worth overdoing."_
1515
Table of contents to jump straight to the problem you're looking for.
1616

1717
<details open>
18-
<summary>2024 (24x⭐)</summary>
18+
<summary>2024 (26x⭐)</summary>
1919

2020
| Day | Title | Stars |
2121
|:---:|:-----------------------------------------------------------|:-----:|
@@ -31,6 +31,7 @@ Table of contents to jump straight to the problem you're looking for.
3131
| 10 | [Hoof It](solutions/aockt/y2024/Y2024D10.kt) | ⭐⭐ |
3232
| 11 | [Plutonian Pebbles](solutions/aockt/y2024/Y2024D11.kt) | ⭐⭐ |
3333
| 12 | [Garden Groups](solutions/aockt/y2024/Y2024D12.kt) | ⭐⭐ |
34+
| 13 | [Claw Contraption](solutions/aockt/y2024/Y2024D13.kt) | ⭐⭐ |
3435

3536
</details>
3637

Diff for: inputs/aockt/y2024/d13/input.txt

20.5 KB
Binary file not shown.

Diff for: inputs/aockt/y2024/d13/solution_part1.txt

28 Bytes
Binary file not shown.

Diff for: inputs/aockt/y2024/d13/solution_part2.txt

38 Bytes
Binary file not shown.

Diff for: solutions/aockt/y2024/Y2024D13.kt

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package aockt.y2024
2+
3+
import aockt.util.parse
4+
import aockt.util.spacial.Point
5+
import io.github.jadarma.aockt.core.Solution
6+
7+
object Y2024D13 : Solution {
8+
9+
/**
10+
* The configuration of a crane machine. The arm starts at the [Point.Origin].
11+
* @property prize The coordinate of the prize.
12+
* @property a The delta the arm will move when pressing the A button.
13+
* @property b The delta the arm will move when pressing the B button.
14+
*/
15+
private data class CraneMachine(val prize: Point, val a: Point, val b: Point) {
16+
init {
17+
require(listOf(prize.x, prize.y, a.x, a.y, b.x, b.y).all { it > 0 }) { "Crane values must be positive." }
18+
require(a != b) { "Crane buttons A and B must have different offsets." }
19+
}
20+
21+
/** The total tokens required to play and win, or `null` if the machine is rigged and there is no solution. */
22+
val costToSolve: Long? by lazy {
23+
// Explanation: To win, we need to find integer solutions n and m such that:
24+
// a.x * n + b.x * m == prize.x and a.y * n + b.y * m == prize.y
25+
// Solving it on paper gives us the following formulas:
26+
val n = (prize.x * b.y - prize.y * b.x).toDouble() / (a.x * b.y - b.x * a.y)
27+
val m = (prize.x - a.x * n) / b.x
28+
if (n % 1 != 0.0 || m % 1 != 0.0) null
29+
else n.toLong() * 3 + m.toLong()
30+
}
31+
}
32+
33+
/**
34+
* Parse the [input] and return the configurations of the [CraneMachine]s.
35+
* If [extraLong], will move the prize very far away.
36+
*/
37+
private fun parseInput(input: String, extraLong: Boolean): List<CraneMachine> = parse {
38+
val regex = Regex("""Button A: X\+(\d+), Y\+(\d+)\nButton B: X\+(\d+), Y\+(\d+)\nPrize: X=(\d+), Y=(\d+)""")
39+
val prizeDelta = if (extraLong) 10_000_000_000_000L else 0L
40+
input
41+
.split("\n\n")
42+
.map { regex.matchEntire(it)!!.destructured }
43+
.map { (ax, ay, bx, by, px, py) ->
44+
CraneMachine(
45+
prize = Point(px.toLong() + prizeDelta, py.toLong() + prizeDelta),
46+
a = Point(ax.toLong(), ay.toLong()),
47+
b = Point(bx.toLong(), by.toLong()),
48+
)
49+
}
50+
}
51+
52+
override fun partOne(input: String): Long = parseInput(input, false).mapNotNull(CraneMachine::costToSolve).sum()
53+
override fun partTwo(input: String): Long = parseInput(input, true ).mapNotNull(CraneMachine::costToSolve).sum()
54+
}

Diff for: tests/aockt/y2024/Y2024D13Test.kt

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package aockt.y2024
2+
3+
import io.github.jadarma.aockt.test.AdventDay
4+
import io.github.jadarma.aockt.test.AdventSpec
5+
6+
@AdventDay(2024, 13, "Claw Contraption")
7+
class Y2024D13Test : AdventSpec<Y2024D13>({
8+
9+
val exampleInput = """
10+
Button A: X+94, Y+34
11+
Button B: X+22, Y+67
12+
Prize: X=8400, Y=5400
13+
14+
Button A: X+26, Y+66
15+
Button B: X+67, Y+21
16+
Prize: X=12748, Y=12176
17+
18+
Button A: X+17, Y+86
19+
Button B: X+84, Y+37
20+
Prize: X=7870, Y=6450
21+
22+
Button A: X+69, Y+23
23+
Button B: X+27, Y+71
24+
Prize: X=18641, Y=10279
25+
""".trimIndent()
26+
27+
partOne { exampleInput shouldOutput 480 }
28+
partTwo { exampleInput shouldOutput 875_318_608_908 }
29+
})

0 commit comments

Comments
 (0)