generated from kotlin-hands-on/advent-of-code-kotlin-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay10.kt
105 lines (92 loc) · 2.85 KB
/
Day10.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
package year2022.`10`
import readInput
sealed class Command {
object NOP : Command()
data class Addx(val amount: Int) : Command()
companion object {
fun from(string: String): Command {
val items = string.split(" ")
return when (items[0]) {
"addx" -> Addx(items[1].toInt())
"noop" -> NOP
else -> error("!!")
}
}
}
}
fun main() {
fun cacheSignalIfConditionMet(
currentCycle: Int,
currentSignal: Int,
results: MutableList<Int>,
) {
if (currentCycle == 20 || ((currentCycle - 20) % 40 == 0)) {
results.add(currentSignal * currentCycle)
}
}
fun drawPixel(
currentCycle: Int,
currentSignal: Int,
stringRes: StringBuilder
) {
val width = 40
val pixelToDraw = ((currentCycle - 1) % width)
val spriteRange = (pixelToDraw - 1..pixelToDraw + 1)
val symbol = if (currentSignal in spriteRange) {
"%"
} else {
"."
}
stringRes.append(symbol)
if (pixelToDraw + 1 == width) {
stringRes.appendLine()
}
}
fun iterateOver(
commands: List<Command>,
doEachCycle: (cycle: Int, signal: Int) -> Unit
) {
var currentCycle = 1
var currentSignal = 1
val iterator = commands.iterator()
while (iterator.hasNext()) {
when (val command = iterator.next()) {
is Command.Addx -> {
repeat(2) {
doEachCycle(currentCycle, currentSignal)
if (it == 1) currentSignal += command.amount
currentCycle++
}
}
Command.NOP -> {
doEachCycle(currentCycle, currentSignal)
currentCycle++
}
}
}
}
fun part1(input: List<String>): Int {
val commands = input.map { Command.from(it) }
val results = mutableListOf<Int>()
iterateOver(commands) { currentCycle, currentValue ->
cacheSignalIfConditionMet(currentCycle, currentValue, results)
}
return results.sum()
}
fun part2(input: List<String>): String {
val commands = input.map { Command.from(it) }
val stringRes = StringBuilder()
iterateOver(commands) { currentCycle, currentValue ->
drawPixel(currentCycle, currentValue, stringRes)
}
return stringRes.toString()
}
// test if implementation meets criteria from the description, like:
val testInput = readInput("Day10_test")
val part1Test = part1(testInput)
println(part1Test)
check(part1Test == 13140)
val input = readInput("Day10")
println(part1(input))
println(part2(input))
}