Prepare for other years
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
package be.vandewalleh.aoc.days
|
||||
|
||||
import be.vandewalleh.aoc.utils.input.Day
|
||||
import be.vandewalleh.aoc.utils.input.Groups
|
||||
import be.vandewalleh.aoc.utils.input.Input
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
@Day(19)
|
||||
class Day19(@Groups val input: Input<List<List<String>>>) {
|
||||
private val rules = input.value[0]
|
||||
private val messages = input.value[1]
|
||||
|
||||
sealed class Rule {
|
||||
data class CharRule(val value: Char) : Rule()
|
||||
data class OrRule(val a: List<Int>, val b: List<Int>?) : Rule() {
|
||||
val all get() = listOfNotNull(a, b)
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseRules(): Map<Int, Rule> {
|
||||
val parsedRules = mutableMapOf<Int, Rule>()
|
||||
rules.forEach {
|
||||
val parts = it.split(":", limit = 2)
|
||||
val index = parts[0].toInt()
|
||||
val rule = if ("\"" !in parts[1]) {
|
||||
val p = parts[1].split('|', limit = 2).map { it.trim().split(" ").mapTo(ArrayList(2)) { it.toInt() } }
|
||||
Rule.OrRule(p[0], if (p.size == 2) p[1] else null)
|
||||
} else {
|
||||
Rule.CharRule(parts[1].trim().replace("\"", "")[0])
|
||||
}
|
||||
parsedRules[index] = rule
|
||||
}
|
||||
return parsedRules
|
||||
}
|
||||
|
||||
private fun matches(input: String, queue: ArrayDeque<Int>, rules: Map<Int, Rule>): Boolean =
|
||||
if (queue.isEmpty()) input.isEmpty()
|
||||
else if (input.isEmpty()) queue.isEmpty()
|
||||
else when (val rule = rules[queue.pop()]!!) {
|
||||
is Rule.CharRule -> input[0] == rule.value && matches(input.drop(1), queue, rules)
|
||||
is Rule.OrRule -> rule.all.any { matches(input, queue.clone().apply { it.asReversed().forEach { addFirst(it) } }, rules) }
|
||||
}
|
||||
|
||||
fun part1(): Int {
|
||||
val rules = parseRules()
|
||||
return messages.count { matches(it, ArrayDeque<Int>().apply { add(0) }, rules) }
|
||||
}
|
||||
|
||||
fun part2(): Int {
|
||||
val rules = parseRules().toMutableMap()
|
||||
rules[8] = Rule.OrRule(listOf(42), listOf(42, 8))
|
||||
rules[11] = Rule.OrRule(listOf(42, 31), listOf(42, 11, 31))
|
||||
return messages.count { matches(it, ArrayDeque<Int>().apply { add(0) }, rules) }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user