Day19 part2
This commit is contained in:
parent
d793a47801
commit
0b1ae6e334
@ -4,135 +4,22 @@ import be.vandewalleh.aoc.utils.input.Day
|
|||||||
import be.vandewalleh.aoc.utils.input.Groups
|
import be.vandewalleh.aoc.utils.input.Groups
|
||||||
import be.vandewalleh.aoc.utils.input.Input
|
import be.vandewalleh.aoc.utils.input.Input
|
||||||
import be.vandewalleh.aoc.utils.input.createDay
|
import be.vandewalleh.aoc.utils.input.createDay
|
||||||
import org.slf4j.LoggerFactory
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
sealed class Rule {
|
|
||||||
data class CharRule(val value: Char) : Rule()
|
|
||||||
data class OrRule(val a: List<Int>, val b: List<Int>?) : Rule()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Day(19)
|
@Day(19)
|
||||||
class Day19(@Groups val input: Input<List<List<String>>>) {
|
class Day19(@Groups val input: Input<List<List<String>>>) {
|
||||||
private val rules = input.value[0]
|
private val rules = input.value[0]
|
||||||
private val messages = input.value[1]
|
private val messages = input.value[1]
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger("Day19")
|
sealed class Rule {
|
||||||
|
data class CharRule(val value: Char) : Rule()
|
||||||
// [[a], [b]] -> [ab]
|
data class OrRule(val a: List<Int>, val b: List<Int>?) : Rule() {
|
||||||
// [[a], [ab, ba]] -> [aab, aba]
|
val all get() = listOfNotNull(a, b)
|
||||||
// [[ab, ba], [a]] -> [aba, baa]
|
|
||||||
// [[a], [b], [c]] -> [abc]
|
|
||||||
// [[ab], [cd], [e]] -> [abcde]
|
|
||||||
// [[ab, ba], [cd, e]] -> [abcd, abe, bacd, bae]
|
|
||||||
// [[ab, ba], [cd, e], [yy, z] -> [abcdyy, abcdz, abeyy, abez, bacdyy, bacdz, baeyy, baez]
|
|
||||||
private fun combine(lists: List<List<String>>) = lists.reduce { acc, list -> combine(acc, list) }
|
|
||||||
|
|
||||||
private fun combine(a: List<String>, b: List<String>): MutableList<String> {
|
|
||||||
val combinations = mutableListOf<String>()
|
|
||||||
a.forEach { f ->
|
|
||||||
b.forEach { s ->
|
|
||||||
combinations.add(f + s)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return combinations
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateSolutions(
|
private fun parseRules(): Map<Int, Rule> {
|
||||||
chars: MutableMap<Int, Char>,
|
|
||||||
rules: MutableMap<Int, MutableList<MutableList<Int>>>,
|
|
||||||
): Map<Int, List<String>> {
|
|
||||||
|
|
||||||
val solutions = mutableMapOf<Int, MutableList<String>>()
|
|
||||||
|
|
||||||
for ((index, char) in chars) {
|
|
||||||
solutions[index] = mutableListOf(char.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun debug() {
|
|
||||||
if(logger.isDebugEnabled){
|
|
||||||
logger.debug("---")
|
|
||||||
logger.debug(rules.entries.joinToString("\n"))
|
|
||||||
val prettySolutions = buildString {
|
|
||||||
append("\nsolutions:")
|
|
||||||
appendLine()
|
|
||||||
solutions.entries.forEach { (k, v) ->
|
|
||||||
append(k)
|
|
||||||
append(" [")
|
|
||||||
appendLine()
|
|
||||||
v.forEach {
|
|
||||||
append("\t")
|
|
||||||
append(it)
|
|
||||||
append("\n")
|
|
||||||
}
|
|
||||||
append("]")
|
|
||||||
appendLine()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.debug(prettySolutions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug()
|
|
||||||
|
|
||||||
while (rules.isNotEmpty()) {
|
|
||||||
val mapIterator = rules.iterator()
|
|
||||||
while (mapIterator.hasNext()) {
|
|
||||||
val (k, values) = mapIterator.next()
|
|
||||||
|
|
||||||
val valueIterator = values.iterator()
|
|
||||||
while (valueIterator.hasNext()) {
|
|
||||||
val value: MutableList<Int> = valueIterator.next()
|
|
||||||
|
|
||||||
if (value.any { rules.contains(it) }) continue
|
|
||||||
|
|
||||||
val sol = value.mapNotNull { solutions[it] }
|
|
||||||
if (sol.size != value.size) continue
|
|
||||||
|
|
||||||
val solution = solutions.computeIfAbsent(k) { mutableListOf() }
|
|
||||||
|
|
||||||
val combined = combine(sol)
|
|
||||||
solution.addAll(combine(sol))
|
|
||||||
|
|
||||||
if(logger.isDebugEnabled){
|
|
||||||
logger.debug(":::$k")
|
|
||||||
logger.debug(":::$value")
|
|
||||||
logger.debug(":::$sol -> $combined")
|
|
||||||
}
|
|
||||||
|
|
||||||
valueIterator.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (values.isEmpty()) mapIterator.remove()
|
|
||||||
}
|
|
||||||
debug()
|
|
||||||
}
|
|
||||||
|
|
||||||
return solutions
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun matches(input: String, solution: List<String>) = solution.any { it == input }
|
|
||||||
|
|
||||||
fun part1(): Int {
|
|
||||||
val parsedRules = parseRules()
|
|
||||||
|
|
||||||
val chars = mutableMapOf<Int, Char>()
|
|
||||||
val rules = mutableMapOf<Int, MutableList<MutableList<Int>>>()
|
|
||||||
|
|
||||||
for ((index, rule) in parsedRules) {
|
|
||||||
when (rule) {
|
|
||||||
is Rule.CharRule -> chars[index] = rule.value
|
|
||||||
is Rule.OrRule -> listOfNotNull(rule.a, rule.b)
|
|
||||||
.forEach { rules.computeIfAbsent(index) { mutableListOf() }.add(it.toMutableList()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val solutions: Map<Int, List<String>> = generateSolutions(chars, rules)
|
|
||||||
val zero = solutions[0]!!
|
|
||||||
|
|
||||||
return messages.count { matches(it, zero) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseRules(): MutableMap<Int, Rule> {
|
|
||||||
val parsedRules = mutableMapOf<Int, Rule>()
|
val parsedRules = mutableMapOf<Int, Rule>()
|
||||||
rules.forEach {
|
rules.forEach {
|
||||||
val parts = it.split(":", limit = 2)
|
val parts = it.split(":", limit = 2)
|
||||||
@ -148,9 +35,26 @@ class Day19(@Groups val input: Input<List<List<String>>>) {
|
|||||||
return parsedRules
|
return parsedRules
|
||||||
}
|
}
|
||||||
|
|
||||||
fun part2() {
|
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) }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun main() = with(createDay<Day19>()) {
|
fun main() = with(createDay<Day19>()) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user