aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortchojnacki <tomaszchojnacki2001@gmail.com>2021-12-14 12:16:23 +0100
committertchojnacki <tomaszchojnacki2001@gmail.com>2021-12-14 12:16:23 +0100
commitd0690ab93cb82efe575d77d117426ab2d5eafaa9 (patch)
tree5a65f8047f2507eaa23a399044e7478878484d4d /src
parentaa6edaafc8ec598197a8c06b6326a0075e78bba4 (diff)
downloadgleam_aoc2020-d0690ab93cb82efe575d77d117426ab2d5eafaa9.tar.gz
gleam_aoc2020-d0690ab93cb82efe575d77d117426ab2d5eafaa9.zip
Finish day 10
Diffstat (limited to 'src')
-rw-r--r--src/Day10.kt88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/Day10.kt b/src/Day10.kt
new file mode 100644
index 0000000..9985014
--- /dev/null
+++ b/src/Day10.kt
@@ -0,0 +1,88 @@
+enum class ChunkDelimeter(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): ChunkDelimeter = values().find { it.open == character || it.close == character }!!
+ }
+}
+
+sealed class SyntaxError {
+ object None : SyntaxError()
+ class IncompleteLine(private val stack: ArrayDeque<ChunkDelimeter>) : SyntaxError() {
+ val score: Long
+ get() {
+ fun delimeterValue(delimeter: ChunkDelimeter): Int = when (delimeter) {
+ ChunkDelimeter.Parentheses -> 1
+ ChunkDelimeter.Brackets -> 2
+ ChunkDelimeter.Braces -> 3
+ ChunkDelimeter.Angled -> 4
+ }
+
+ return stack.fold(0) { acc, elem -> acc * 5 + delimeterValue(elem) }
+ }
+ }
+ class CorruptedLine(private val invalidDelimeter: ChunkDelimeter) : SyntaxError() {
+ val score: Int
+ get() = when (invalidDelimeter) {
+ ChunkDelimeter.Parentheses -> 3
+ ChunkDelimeter.Brackets -> 57
+ ChunkDelimeter.Braces -> 1197
+ ChunkDelimeter.Angled -> 25137
+ }
+ }
+}
+
+fun parse(line: String): SyntaxError {
+ val stack = ArrayDeque<ChunkDelimeter>()
+
+ for (char in line) {
+ when {
+ ChunkDelimeter.isOpening(char) -> stack.addFirst(ChunkDelimeter.from(char))
+ ChunkDelimeter.isClosing(char) -> {
+ val closingDelimeter = ChunkDelimeter.from(char)
+ if (stack.first() == closingDelimeter) {
+ stack.removeFirst()
+ } else {
+ return SyntaxError.CorruptedLine(closingDelimeter)
+ }
+ }
+ }
+ }
+
+ if (stack.isNotEmpty()) {
+ return SyntaxError.IncompleteLine(stack)
+ }
+
+ return SyntaxError.None
+}
+
+fun main() {
+ 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] }
+
+
+ val testInput = readInputAsLines("Day10_test")
+ check(part1(testInput) == 26397)
+ check(part2(testInput) == 288957L)
+
+ val input = readInputAsLines("Day10")
+ println(part1(input))
+ println(part2(input))
+}