aboutsummaryrefslogtreecommitdiff
path: root/aoc-2021-kotlin/src/Day10.kt
diff options
context:
space:
mode:
Diffstat (limited to 'aoc-2021-kotlin/src/Day10.kt')
-rw-r--r--aoc-2021-kotlin/src/Day10.kt91
1 files changed, 91 insertions, 0 deletions
diff --git a/aoc-2021-kotlin/src/Day10.kt b/aoc-2021-kotlin/src/Day10.kt
new file mode 100644
index 0000000..d6d026c
--- /dev/null
+++ b/aoc-2021-kotlin/src/Day10.kt
@@ -0,0 +1,91 @@
+object Day10 {
+ private enum class ChunkDelimiter(val open: Char, val close: Char) {
+ Parentheses('(', ')'),
+ Brackets('[', ']'),
+ Braces('{', '}'),
+ Angled('<', '>');
+
+ companion object {
+ fun isOpening(character: Char): Boolean = values().any { it.open == character }
+ fun isClosing(character: Char): Boolean = values().any { it.close == character }
+ fun from(character: Char): ChunkDelimiter =
+ values().find { it.open == character || it.close == character }!!
+ }
+ }
+
+ private sealed class SyntaxError {
+ object None : SyntaxError()
+ class IncompleteLine(private val stack: ArrayDeque<ChunkDelimiter>) : SyntaxError() {
+ val score: Long
+ get() {
+ fun delimiterValue(delimiter: ChunkDelimiter): Int = when (delimiter) {
+ ChunkDelimiter.Parentheses -> 1
+ ChunkDelimiter.Brackets -> 2
+ ChunkDelimiter.Braces -> 3
+ ChunkDelimiter.Angled -> 4
+ }
+
+ return stack.fold(0) { acc, elem -> acc * 5 + delimiterValue(elem) }
+ }
+ }
+
+ class CorruptedLine(private val invalidDelimiter: ChunkDelimiter) : SyntaxError() {
+ val score: Int
+ get() = when (invalidDelimiter) {
+ ChunkDelimiter.Parentheses -> 3
+ ChunkDelimiter.Brackets -> 57
+ ChunkDelimiter.Braces -> 1197
+ ChunkDelimiter.Angled -> 25137
+ }
+ }
+ }
+
+ private fun parse(line: String): SyntaxError {
+ val stack = ArrayDeque<ChunkDelimiter>()
+
+ for (char in line) {
+ when {
+ ChunkDelimiter.isOpening(char) -> stack.addFirst(ChunkDelimiter.from(char))
+ ChunkDelimiter.isClosing(char) -> {
+ val closingDelimiter = ChunkDelimiter.from(char)
+ if (stack.first() == closingDelimiter) {
+ stack.removeFirst()
+ } else {
+ return SyntaxError.CorruptedLine(closingDelimiter)
+ }
+ }
+ }
+ }
+
+ if (stack.isNotEmpty()) {
+ return SyntaxError.IncompleteLine(stack)
+ }
+
+ return SyntaxError.None
+ }
+
+ fun part1(input: List<String>): Int = input
+ .map { parse(it) }
+ .filterIsInstance<SyntaxError.CorruptedLine>()
+ .sumOf { it.score }
+
+ fun part2(input: List<String>): Long =
+ input
+ .asSequence()
+ .map { parse(it) }
+ .filterIsInstance<SyntaxError.IncompleteLine>()
+ .map { it.score }
+ .sorted()
+ .toList()
+ .let { it[it.size / 2] }
+}
+
+fun main() {
+ val testInput = readInputAsLines("Day10_test")
+ check(Day10.part1(testInput) == 26397)
+ check(Day10.part2(testInput) == 288957L)
+
+ val input = readInputAsLines("Day10")
+ println(Day10.part1(input))
+ println(Day10.part2(input))
+}