diff options
Diffstat (limited to 'src/Day18.kt')
-rw-r--r-- | src/Day18.kt | 175 |
1 files changed, 88 insertions, 87 deletions
diff --git a/src/Day18.kt b/src/Day18.kt index f69e916..84575b7 100644 --- a/src/Day18.kt +++ b/src/Day18.kt @@ -1,114 +1,114 @@ import kotlin.math.ceil import kotlin.math.floor -class SnailfishNum private constructor(private val data: MutableList<Entry>) { - data class Entry(var num: Int, val depth: Int) - - companion object { - fun parse(input: String): SnailfishNum { - var depth = 0 - val list = mutableListOf<Entry>() - - for (char in input) { - when (char) { - '[' -> depth += 1 - ']' -> depth -= 1 - ',' -> {} - else -> list.add(Entry(char.toString().toInt(), depth)) +object Day18 { + private class SnailfishNum private constructor(private val data: MutableList<Entry>) { + private data class Entry(var num: Int, val depth: Int) + + companion object { + fun parse(input: String): SnailfishNum { + var depth = 0 + val list = mutableListOf<Entry>() + + for (char in input) { + when (char) { + '[' -> depth += 1 + ']' -> depth -= 1 + ',' -> {} + else -> list.add(Entry(char.toString().toInt(), depth)) + } } - } - return SnailfishNum(list) + return SnailfishNum(list) + } } - } - private val shouldExplode - get() = data - .zipWithNext() - .any { it.first.depth == it.second.depth && it.first.depth >= 5 } + private val shouldExplode + get() = data + .zipWithNext() + .any { it.first.depth == it.second.depth && it.first.depth >= 5 } - private val shouldSplit - get() = data.any { it.num >= 10 } + private val shouldSplit + get() = data.any { it.num >= 10 } - private fun explode() { - val (leftIndex, rightIndex) = data - .zipWithNext() - .indexOfFirst { it.first.depth == it.second.depth && it.first.depth >= 5 } - .let { it to it + 1 } + private fun explode() { + val (leftIndex, rightIndex) = data + .zipWithNext() + .indexOfFirst { it.first.depth == it.second.depth && it.first.depth >= 5 } + .let { it to it + 1 } - if (leftIndex - 1 in data.indices) { - data[leftIndex - 1].num += data[leftIndex].num - } + if (leftIndex - 1 in data.indices) { + data[leftIndex - 1].num += data[leftIndex].num + } - if (rightIndex + 1 in data.indices) { - data[rightIndex + 1].num += data[rightIndex].num - } + if (rightIndex + 1 in data.indices) { + data[rightIndex + 1].num += data[rightIndex].num + } - data[leftIndex] = Entry(0, data[leftIndex].depth - 1) - data.removeAt(rightIndex) - } + data[leftIndex] = Entry(0, data[leftIndex].depth - 1) + data.removeAt(rightIndex) + } - private fun split() { - val index = data.indexOfFirst { it.num >= 10 } - val depth = data[index].depth + private fun split() { + val index = data.indexOfFirst { it.num >= 10 } + val depth = data[index].depth - val half = data[index].num / 2.0 - val roundedDown = floor(half).toInt() - val roundedUp = ceil(half).toInt() + val half = data[index].num / 2.0 + val roundedDown = floor(half).toInt() + val roundedUp = ceil(half).toInt() - data[index] = Entry(roundedUp, depth + 1) - data.add(index, Entry(roundedDown, depth + 1)) - } + data[index] = Entry(roundedUp, depth + 1) + data.add(index, Entry(roundedDown, depth + 1)) + } - private fun reduce() { - while (true) { - if (shouldExplode) { - explode() - } else if (shouldSplit) { - split() - } else { - break + private fun reduce() { + while (true) { + if (shouldExplode) { + explode() + } else if (shouldSplit) { + split() + } else { + break + } } } - } - fun magnitude(): Int { - val dataCopy = data.toMutableList() + fun magnitude(): Int { + val dataCopy = data.toMutableList() - while (dataCopy.size > 1) { - val maxDepth = dataCopy.maxOf { it.depth } + while (dataCopy.size > 1) { + val maxDepth = dataCopy.maxOf { it.depth } - val (leftIndex, rightIndex) = dataCopy - .zipWithNext() - .indexOfFirst { it.first.depth == it.second.depth && it.first.depth == maxDepth } - .let { it to it + 1 } + val (leftIndex, rightIndex) = dataCopy + .zipWithNext() + .indexOfFirst { it.first.depth == it.second.depth && it.first.depth == maxDepth } + .let { it to it + 1 } - dataCopy[leftIndex] = Entry( - dataCopy[leftIndex].num * 3 + dataCopy[rightIndex].num * 2, - maxDepth - 1 - ) - dataCopy.removeAt(rightIndex) + dataCopy[leftIndex] = Entry( + dataCopy[leftIndex].num * 3 + dataCopy[rightIndex].num * 2, + maxDepth - 1 + ) + dataCopy.removeAt(rightIndex) + } + + return dataCopy.first().num } - return dataCopy.first().num + operator fun plus(other: SnailfishNum): SnailfishNum = + SnailfishNum( + (this.data + other.data).map { Entry(it.num, it.depth + 1) }.toMutableList() + ).also { it.reduce() } } - operator fun plus(other: SnailfishNum): SnailfishNum = - SnailfishNum( - (this.data + other.data).map { Entry(it.num, it.depth + 1) }.toMutableList() - ).also { it.reduce() } -} - -fun <T> combinations(items: Sequence<T>): Sequence<Pair<T, T>> = - sequence { - items.forEach { a -> - items.forEach { b -> - yield(a to b) + private fun <T> combinations(items: Sequence<T>): Sequence<Pair<T, T>> = + sequence { + items.forEach { a -> + items.forEach { b -> + yield(a to b) + } } } - } -fun main() { fun part1(input: List<String>): Int = input .asSequence() @@ -124,13 +124,14 @@ fun main() { ) .filter { it.first !== it.second } .maxOf { (it.first + it.second).magnitude() } +} - +fun main() { val testInput = readInputAsLines("Day18_test") - check(part1(testInput) == 4140) - check(part2(testInput) == 3993) + check(Day18.part1(testInput) == 4140) + check(Day18.part2(testInput) == 3993) val input = readInputAsLines("Day18") - println(part1(input)) - println(part2(input)) + println(Day18.part1(input)) + println(Day18.part2(input)) } |