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.Input
|
||||
import be.vandewalleh.aoc.utils.input.createDay
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
sealed class Rule {
|
||||
data class CharRule(val value: Char) : Rule()
|
||||
data class OrRule(val a: List<Int>, val b: List<Int>?) : Rule()
|
||||
}
|
||||
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]
|
||||
|
||||
private val logger = LoggerFactory.getLogger("Day19")
|
||||
|
||||
// [[a], [b]] -> [ab]
|
||||
// [[a], [ab, ba]] -> [aab, aba]
|
||||
// [[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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
return combinations
|
||||
}
|
||||
|
||||
private fun generateSolutions(
|
||||
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> {
|
||||
private fun parseRules(): Map<Int, Rule> {
|
||||
val parsedRules = mutableMapOf<Int, Rule>()
|
||||
rules.forEach {
|
||||
val parts = it.split(":", limit = 2)
|
||||
@ -148,9 +35,26 @@ class Day19(@Groups val input: Input<List<List<String>>>) {
|
||||
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>()) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user