From d0690ab93cb82efe575d77d117426ab2d5eafaa9 Mon Sep 17 00:00:00 2001 From: tchojnacki Date: Tue, 14 Dec 2021 12:16:23 +0100 Subject: Finish day 10 --- README.md | 6 ++--- src/Day10.kt | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 src/Day10.kt diff --git a/README.md b/README.md index 32a01b7..23b4fe7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Advent of Code 2021 in Kotlin ![Kotlin](https://img.shields.io/badge/Kotlin-grey?logo=Kotlin) -![](https://img.shields.io/badge/⭐%20stars-18-yellow) -![](https://img.shields.io/badge/📅%20days-9-blue) +![](https://img.shields.io/badge/⭐%20stars-20-yellow) +![](https://img.shields.io/badge/📅%20days-10-blue) Welcome to the Advent of Code[^aoc] Kotlin project created by [tchojnacki][github] using the [Advent of Code Kotlin Template][template] delivered by JetBrains. @@ -17,7 +17,7 @@ Welcome to the Advent of Code[^aoc] Kotlin project created by [tchojnacki][githu | Day 7: The Treachery of Whales | 🌟 | 🌟 | | Day 8: Seven Segment Search | 🌟 | 🌟 | | Day 9: Smoke Basin | 🌟 | 🌟 | -| Day 10: ??? | | | +| Day 10: Syntax Scoring | 🌟 | 🌟 | | Day 11: ??? | | | | Day 12: ??? | | | | Day 13: ??? | | | 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) : 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() + + 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): Int = input + .map { parse(it) } + .filterIsInstance() + .sumOf { it.score } + + fun part2(input: List): Long = + input + .asSequence() + .map { parse(it) } + .filterIsInstance() + .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)) +} -- cgit v1.2.3