package aoc2023

import println
import readInput
import kotlin.math.max

/*
--- Day 2: Cube Conundrum ---
https://adventofcode.com/2023/day/2
*/
fun main() {

    val inlineTestInput = """
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
"""

    fun part1(input: List<String>): Int {
        val limits = mapOf("red" to 12, "green" to 13, "blue" to 14)
        return input.map {
            "Game (\\d+): (.*)".toRegex().matchEntire(it)?.destructured
                ?.let { (id, game) ->
                    var possible = id.toInt()
                    game.replace(";", "").replace(",", "")
                        .split(" ").chunked(2)
                        .forEach { (num, col) -> if (num.toInt() > limits[col]!!) possible = 0 }
                    possible
                }
        }.sumOf { it!! }
    }

    fun part2(input: List<String>): Int {
        return input.map {
            val lg = it.split(":")
            val sets = lg[1].trim().split(";")
            val powerMap = HashMap<String, Int>()
            for (s in sets) {
                val boxes = s.trim().split(",")
                for (b in boxes) {
                    val (num, col) = b.trim().split(" ")
                    powerMap.merge(col, num.toInt(), ::max)
                }
            }
            powerMap.values.reduce { a, b -> a * b }
        }.sum()
    }

    // test if implementation meets criteria from the description, like:
    val testInput = inlineTestInput.trim().reader().readLines()
    //val testInput = readInput("aoc2023/Day02_test")
    println("Part 1 Test: " + part1(testInput))
    println("Part 2 Test: " + part2(testInput))
    check(part1(testInput) == 8)
    check(part2(testInput) == 2286)

    val input = readInput("aoc2023/Day02")
    part1(input).println()
    part2(input).println()
}
