Hey everyone. I have not yet solved Day7 yet. I wa...
# advent-of-code
d
Hey everyone. I have not yet solved Day7 yet. I want to bang my head against it for a little longer before I look up other solutions. But so far I am building Regex, nested with Regex, which match stuff split with more Regex… and so on. xD At the end, I am building BagRule objects that I can then traverse and check. But I belive there must be a more elegant way to parse the string into one of the objects I defined. Like specifying a grammar in a more elegant form than just Regex. With named elements that are easier to put into an object. Is there some library or something you could suggest? Other than that, I could express everything in one Regex. But the matching groups would be nested, I have no idea how to work with that. My mind was already blown 2-3 days before Day 7 when I found
destructed
😛
Oh wait… Kotlin does support named matching groups… tries something
😂 1
Hmm okay. I think it is less exciting as I hoped. As far as I can tell, matching-groups do not work on repeating things. E.g. matching "xxx" on the Regex
^(x)*$
returns only one matching-group, not three as I have hoped. I was hoping that my captured group would magically turn into an Array or List. =/
I guess one Regex to rule them all will not do. =/
If I could capture repeated groups, this would make it so much more elegant. .Net seems to support that, but Java does not.
j
It's overkill for this problem, but I've always wanted to try and use https://www.antlr.org/ to build parsers for the more complicated AoC inputs.
d
That is what I also came across. I thought about it… xD
I guess since it is day07 and long overdue, posting a spoiler here is ok? It took me way too long and maybe is a little 'too dense' for good readability o.o
Copy code
object Day07 {
    private const val MAX_DEPTH = 99
    private const val SHINY_BAG = "shiny gold"

    private const val colors = """\w+ \w+"""
    private const val noBags = "no other bags"
    private val rule = Regex("""^($colors) bags contain (.*).$""")
    private val rulePart = Regex("""(\d+) ($colors) bags?|$noBags""")

    private fun rulePartsToColors(ruleParts: String): List<String> =
        if (ruleParts.equals(noBags)) listOf() else rulePart.findAll(ruleParts)
            .mapNotNull { it.destructured }
            .map { (_, allowedColor) -> allowedColor }
            .toList()

    private fun canReachShiny(ruleMap: Map<String, List<String>>, query: String): Boolean =
        canReachShinyRecursive(ruleMap, query, 0)

    private fun canReachShinyRecursive(ruleMap: Map<String, List<String>>, query: String, depth: Int): Boolean {
        if (depth > MAX_DEPTH) throw IllegalStateException("Rules to deep! Depth at $depth")
        if (ruleMap[query]?.contains(SHINY_BAG) == true) return true
        return (ruleMap[query]?.any { canReachShinyRecursive(ruleMap, it, depth + 1) } == true)
    }

    fun solve(inputs: List<String>): Int {
        val ruleMap = inputs.mapNotNull { rule.matchEntire(it)?.destructured }
            .map { (subject, ruleParts) -> subject to rulePartsToColors(ruleParts) }
            .toMap()
        return ruleMap.keys.count { canReachShiny(ruleMap, it) }
    }
}