aboutsummaryrefslogtreecommitdiff
path: root/src/Day16.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/Day16.kt')
-rw-r--r--src/Day16.kt218
1 files changed, 112 insertions, 106 deletions
diff --git a/src/Day16.kt b/src/Day16.kt
index f8b287c..d11219d 100644
--- a/src/Day16.kt
+++ b/src/Day16.kt
@@ -1,120 +1,123 @@
-import kotlin.collections.ArrayDeque
-
-sealed class Packet(
- private val bits: Int,
- protected val version: Int,
-) {
- class Literal(
- bits: Int,
- version: Int,
- private val literalValue: Long,
- ) : Packet(bits, version) {
- override fun versionSum(): Int = version
-
- override val value: Long
- get() = literalValue
- }
+object Day16 {
+ private sealed class Packet(
+ private val bits: Int,
+ protected val version: Int,
+ ) {
+ private class Literal(
+ bits: Int,
+ version: Int,
+ private val literalValue: Long,
+ ) : Packet(bits, version) {
+ override fun versionSum(): Int = version
+
+ override val value: Long
+ get() = literalValue
+ }
- class Operator(
- bits: Int,
- version: Int,
- private val typeId: Int,
- private val subpackets: List<Packet>,
- ) : Packet(bits, version) {
- override fun versionSum(): Int = version + subpackets.sumOf { it.versionSum() }
-
- override val value: Long
- get() = when (typeId) {
- 0 -> subpackets.sumOf { it.value }
- 1 -> subpackets.fold(1) { acc, packet -> acc * packet.value }
- 2 -> subpackets.minOf { it.value }
- 3 -> subpackets.maxOf { it.value }
- 5, 6, 7 -> {
- val (first, second) = subpackets.map { it.value }
-
- if (when (typeId) {
- 5 -> first > second
- 6 -> first < second
- 7 -> first == second
- else -> false
- }) {
- 1
- } else {
- 0
+ private class Operator(
+ bits: Int,
+ version: Int,
+ private val typeId: Int,
+ private val subpackets: List<Packet>,
+ ) : Packet(bits, version) {
+ override fun versionSum(): Int = version + subpackets.sumOf { it.versionSum() }
+
+ override val value: Long
+ get() = when (typeId) {
+ 0 -> subpackets.sumOf { it.value }
+ 1 -> subpackets.fold(1) { acc, packet -> acc * packet.value }
+ 2 -> subpackets.minOf { it.value }
+ 3 -> subpackets.maxOf { it.value }
+ 5, 6, 7 -> {
+ val (first, second) = subpackets.map { it.value }
+
+ if (when (typeId) {
+ 5 -> first > second
+ 6 -> first < second
+ 7 -> first == second
+ else -> false
+ }
+ ) {
+ 1
+ } else {
+ 0
+ }
}
+
+ else -> throw IllegalStateException("Illegal packet type id.")
}
- else -> throw IllegalStateException("Illegal packet type id.")
- }
- }
+ }
- abstract fun versionSum(): Int
+ abstract fun versionSum(): Int
- abstract val value: Long
+ abstract val value: Long
- companion object {
- fun parse(bitQueue: ArrayDeque<Char>): Packet {
- var packetBits = 0
+ companion object {
+ fun parse(bitQueue: ArrayDeque<Char>): Packet {
+ var packetBits = 0
- fun takeBits(n: Int): Int {
- packetBits += n
- return (0 until n)
- .joinToString("") { bitQueue.removeFirst().toString() }
- .toInt(2)
- }
+ fun takeBits(n: Int): Int {
+ packetBits += n
+ return (0 until n)
+ .joinToString("") { bitQueue.removeFirst().toString() }
+ .toInt(2)
+ }
- val version = takeBits(3)
+ val version = takeBits(3)
- when (val typeId = takeBits(3)) {
- 4 -> { // Literal packet
- var literalValue = 0L
- while (true) {
- val groupHeader = takeBits(1)
- val groupValue = takeBits(4)
+ when (val typeId = takeBits(3)) {
+ 4 -> { // Literal packet
+ var literalValue = 0L
+ while (true) {
+ val groupHeader = takeBits(1)
+ val groupValue = takeBits(4)
- literalValue = (literalValue shl 4) + groupValue
+ literalValue = (literalValue shl 4) + groupValue
- if (groupHeader == 0) {
- break
+ if (groupHeader == 0) {
+ break
+ }
}
+
+ return Literal(packetBits, version, literalValue)
}
- return Literal(packetBits, version, literalValue)
- }
- else -> { // Operator packet
- val subpackets = mutableListOf<Packet>()
-
- when (takeBits(1)) {
- 0 -> {
- val subpacketLength = takeBits(15)
-
- var currentSubpacketLength = 0
- while (currentSubpacketLength < subpacketLength) {
- val subpacket = parse(bitQueue)
- currentSubpacketLength += subpacket.bits
- subpackets.add(subpacket)
+ else -> { // Operator packet
+ val subpackets = mutableListOf<Packet>()
+
+ when (takeBits(1)) {
+ 0 -> {
+ val subpacketLength = takeBits(15)
+
+ var currentSubpacketLength = 0
+ while (currentSubpacketLength < subpacketLength) {
+ val subpacket = parse(bitQueue)
+ currentSubpacketLength += subpacket.bits
+ subpackets.add(subpacket)
+ }
}
- }
- 1 -> {
- val subpacketCount = takeBits(11)
- repeat(subpacketCount) {
- subpackets.add(parse(bitQueue))
+ 1 -> {
+ val subpacketCount = takeBits(11)
+
+ repeat(subpacketCount) {
+ subpackets.add(parse(bitQueue))
+ }
}
+
+ else -> throw IllegalStateException("Illegal length type id.")
}
- else -> throw IllegalStateException("Illegal length type id.")
- }
- packetBits += subpackets.sumOf { it.bits }
+ packetBits += subpackets.sumOf { it.bits }
- return Operator(packetBits, version, typeId, subpackets)
+ return Operator(packetBits, version, typeId, subpackets)
+ }
}
}
}
}
-}
-fun main() {
- fun parse(input: String): Packet {
+ private fun parse(input: String): Packet {
val bitQueue = ArrayDeque(
input
.flatMap {
@@ -133,23 +136,26 @@ fun main() {
fun part1(input: String): Int = parse(input).versionSum()
fun part2(input: String): Long = parse(input).value
+}
+
- check(part1("8A004A801A8002F478") == 16)
- check(part1("620080001611562C8802118E34") == 12)
- check(part1("C0015000016115A2E0802F182340") == 23)
- check(part1("A0016C880162017C3686B18A3D4780") == 31)
+fun main() {
+ check(Day16.part1("8A004A801A8002F478") == 16)
+ check(Day16.part1("620080001611562C8802118E34") == 12)
+ check(Day16.part1("C0015000016115A2E0802F182340") == 23)
+ check(Day16.part1("A0016C880162017C3686B18A3D4780") == 31)
- check(part2("C200B40A82") == 3L)
- check(part2("04005AC33890") == 54L)
- check(part2("880086C3E88112") == 7L)
- check(part2("CE00C43D881120") == 9L)
- check(part2("D8005AC2A8F0") == 1L)
- check(part2("F600BC2D8F") == 0L)
- check(part2("9C005AC2F8F0") == 0L)
- check(part2("9C0141080250320F1802104A08") == 1L)
+ check(Day16.part2("C200B40A82") == 3L)
+ check(Day16.part2("04005AC33890") == 54L)
+ check(Day16.part2("880086C3E88112") == 7L)
+ check(Day16.part2("CE00C43D881120") == 9L)
+ check(Day16.part2("D8005AC2A8F0") == 1L)
+ check(Day16.part2("F600BC2D8F") == 0L)
+ check(Day16.part2("9C005AC2F8F0") == 0L)
+ check(Day16.part2("9C0141080250320F1802104A08") == 1L)
val input = readInputAsString("Day16")
- println(part1(input))
- println(part2(input))
+ println(Day16.part1(input))
+ println(Day16.part2(input))
}