package aoc2024

import println
import readInput

/*
--- Day 19: Linen Layout ---
https://adventofcode.com/2024/day/19
*/
fun main() {

    val inlineTestInput = """
r, wr, b, g, bwu, rb, gb, br

brwrr
bggr
gbbr
rrbgbr
ubwu
bwurrg
brgr
bbrgwb
"""

    fun rec(inp: String, towels: Array<String>): Boolean =
        inp.isEmpty() || towels.any { inp.startsWith(it) && rec(inp.substring(it.length), towels) }

    fun part1(input: List<String>): Int {
        val towels = input[0].split(", ").toTypedArray()
        return input.drop(2).count { rec(it, towels) }
    }

    val cache = HashMap<String, Long>()

    fun rec2(inp: String, towels: Array<String>): Long =
        if (inp.isEmpty()) 1 else cache.getOrPut(inp) {
            towels.filter { inp.startsWith(it) }.sumOf { rec2(inp.substring(it.length), towels) }
        }

    fun part2(input: List<String>): Long {
        val towels = input[0].split(", ").toTypedArray()
        return input.drop(2).sumOf { rec2(it, towels) }
    }

    // test if implementation meets criteria from the description, like:
    val testInput = inlineTestInput.trim().reader().readLines()
    //val testInput = readInput("aoc2024/Day19_test")
    val testInputPart1Result = part1(testInput)
    println("Part 1 Test: $testInputPart1Result")
    val testInputPart2Result = part2(testInput)
    println("Part 2 Test: $testInputPart2Result")
    check(testInputPart1Result == 6)
    check(testInputPart2Result == 16L)

    val input = readInput("aoc2024/Day19")
    part1(input).println()
    part2(input).println()
}
