DEV Community

Discussion on: AoC Day 8: Memory Maneuver

Collapse
 
neilgall profile image
Neil Gall

I was missing parser combinators so came back and did day 8 again.

data class Node(val children: List<Node>, val metadata: List<Int>)

fun parse(input: String): Node {
    val integer = Terminals.IntegerLiteral.PARSER.map(String::toInt)

    val treeRef = Parser.Reference<Node>()

    fun nodeParser(numChildren: Int, numMetadata: Int): Parser<Node> =
        sequence(
            treeRef.lazy().times(numChildren),
            integer.times(numMetadata),
            ::Node
        )

    val nodeInfo: Parser<Pair<Int, Int>> = sequence(integer, integer) { nc, nm -> Pair(nc, nm) }
    val tree: Parser<Node> = nodeInfo.next { (nc, nm) -> nodeParser(nc, nm) }
    treeRef.set(tree)

    val parser = tree.from(Terminals.IntegerLiteral.TOKENIZER, Scanners.WHITESPACES)
    return parser.parse(input.trim())
}

It was initially much more dense but I tried to break it up to make it easier to follow. It's not the One True Way of parsing for nothing you know!