generated from kotlin-hands-on/advent-of-code-kotlin-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay13.kt
107 lines (88 loc) · 2.52 KB
/
Day13.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package year2024.`13`
import readInput
private const val CURRENT_DAY = "13"
private data class Point(
val x: Long,
val y: Long,
) {
override fun toString(): String {
return "{$x,$y}"
}
}
private data class Configuration(
val buttonA: Point,
val buttonB: Point,
val prize: Point,
) {
override fun toString(): String {
return "{A:$buttonA, B:$buttonB, $prize}"
}
}
private fun String.toButton(): Point {
val items = this.split("+", ",").mapNotNull {
it.toLongOrNull()
}
return Point(
items[0],
items[1],
)
}
private fun String.toPrize(part2: Boolean = false): Point {
val items = this.split("=", ",").mapNotNull {
it.toIntOrNull()
}
return Point(
items[0] + if (part2) 10000000000000L else 0L,
items[1] + if (part2) 10000000000000L else 0L,
)
}
private fun parseIntoButton(input: List<String>, part2: Boolean = false): List<Configuration> {
return input.windowed(4, 4, true).map { conf ->
Configuration(
buttonA = conf[0].toButton(),
buttonB = conf[1].toButton(),
prize = conf[2].toPrize(part2),
)
}
}
private fun Configuration.minAmountToWin2(): Long? {
val bClick = (prize.y * buttonA.x - prize.x * buttonA.y) / (buttonA.x * buttonB.y - buttonB.x * buttonA.y)
val aClick = (buttonB.y * prize.x - buttonB.x * prize.y) / (buttonB.y * buttonA.x - buttonB.x * buttonA.y)
println("[$bClick,$aClick]")
val resPoint = Point(
buttonA.x * aClick + buttonB.x * bClick,
buttonA.y * aClick + buttonB.y * bClick,
)
println(resPoint)
return if (resPoint == prize) {
aClick * 3L + bClick * 1L
} else {
null
}
}
fun main() {
fun part1(input: List<String>): Long {
val data = parseIntoButton(input)
.mapNotNull { it.minAmountToWin2() }
return data.sum()
}
fun part2(input: List<String>): Long {
val data = parseIntoButton(input, true)
.mapNotNull { it.minAmountToWin2() }
return data.sum()
}
// test if implementation meets criteria from the description, like:
val testInput = readInput("Day${CURRENT_DAY}_test")
val part1Test = part1(testInput)
println(part1Test)
check(part1Test == 480L)
val input = readInput("Day$CURRENT_DAY")
// Part 1
val part1 = part1(input)
println(part1)
check(part1 == 37680L)
// Part 2
val part2 = part2(input)
println(part2)
check(part2 == 87550094242995L)
}