/
Day21.kt
78 lines (67 loc) 路 2.87 KB
/
Day21.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
package com.clouddjr.advent2022
class Day21(input: List<String>) {
private val monkeys = input.map { it.split(": ") }.associate { (monkey, job) -> monkey to job }
private val operations = mapOf(
"+" to { a: Long, b: Long -> a + b },
"-" to { a: Long, b: Long -> a - b },
"*" to { a: Long, b: Long -> a * b },
"/" to { a: Long, b: Long -> a / b }
)
private val leftReversedOperations = operations.mapKeys {
when (it.key) {
"+" -> "-"
"-" -> "+"
"*" -> "/"
else -> "*"
}
}
private val rightReversedOperations = mapOf(
"+" to { a: Long, b: Long -> a - b },
"-" to { a: Long, b: Long -> b - a },
"*" to { a: Long, b: Long -> a / b },
"/" to { a: Long, b: Long -> b / a }
)
fun solvePart1() = findNumberToYell("root")
fun solvePart2() = findMyNumberToYell()
private fun findNumberToYell(monkey: String): Long {
val job = monkeys[monkey]!!
return when (val number = job.toLongOrNull()) {
null -> {
val first = job.substringBefore(" ")
val second = job.substringAfterLast(" ")
val op = job.substringAfter(" ").substringBefore(" ")
operations[op]!!(findNumberToYell(first), findNumberToYell(second))
}
else -> number
}
}
private fun findMyNumberToYell(): Long {
val rootJob = monkeys["root"]!!
val (firstOp, first) = findOperations(rootJob.substringBefore(" "))
val (secondOp, second) = findOperations(rootJob.substringAfterLast(" "))
return firstOp.ifEmpty { secondOp }.reversed().map { it.split(" ") }.fold(first ?: second!!) { acc, (f, s) ->
when (f in operations.keys) {
true -> leftReversedOperations[f]!!(acc, s.toLong())
false -> rightReversedOperations[s]!!(acc, f.toLong())
}
}
}
private fun findOperations(monkey: String): Pair<List<String>, Long?> {
if (monkey == "humn") return emptyList<String>() to null
val job = monkeys[monkey]!!
return when (val number = job.toLongOrNull()) {
null -> {
val (firstOp, first) = findOperations(job.substringBefore(" "))
val (secondOp, second) = findOperations(job.substringAfterLast(" "))
val op = job.substringAfter(" ").substringBefore(" ")
when {
first != null && second != null -> emptyList<String>() to operations[op]!!(first, second)
first == null && second != null -> firstOp + "$op $second" to null
first != null && second == null -> secondOp + "$first $op" to null
else -> error("Unsupported state")
}
}
else -> emptyList<String>() to number
}
}
}