package org.example.e3fxgaming.adventOfCode.aoc2023.day02

import org.example.e3fxgaming.adventOfCode.utility.Day
import org.example.e3fxgaming.adventOfCode.utility.IndividualLineInputParser
import org.example.e3fxgaming.adventOfCode.utility.InputParser

class Day02(inputLines: String) : Day<List<Triple<Int, Int, Int>>, List<Triple<Int, Int, Int>>> {
    override val partOneParser: InputParser<List<Triple<Int, Int, Int>>> =
        object : IndividualLineInputParser<List<Triple<Int, Int, Int>>>(inputLines) {
            override fun parseLine(line: String): List<Triple<Int, Int, Int>> {
                return line.substringAfter(": ").split("; ").map { round ->
                    IntArray(3).also { rgb ->
                        round.split(", ").forEach { countAndColor ->
                            val (count, color) = countAndColor.split(" ")
                            when (color) {
                                "red" -> rgb[0] = count.toInt()
                                "green" -> rgb[1] = count.toInt()
                                "blue" -> rgb[2] = count.toInt()
                            }
                        }
                    }.let { tripleDesc ->
                        Triple(tripleDesc[0], tripleDesc[1], tripleDesc[2])
                    }
                }
            }
        }

    override val partTwoParser: InputParser<List<Triple<Int, Int, Int>>> = partOneParser


    private fun Triple<Int, Int, Int>.allowed() = first <= 12 && second <= 13 && third <= 14

    override fun solveFirst(given: List<List<Triple<Int, Int, Int>>>): String {
        return given.withIndex().fold(0) { acc, (index, gameRecording) ->
            if (gameRecording.any { !it.allowed() }) {
                return@fold acc
            }

            acc + (index + 1)
        }.toString()
    }

    override fun solveSecond(given: List<List<Triple<Int, Int, Int>>>): String {
        return given.sumOf { drawingRecordings ->
            var r = 0
            var g = 0
            var b = 0

            drawingRecordings.forEach { triple ->
                r = r.coerceAtLeast(triple.first)
                g = g.coerceAtLeast(triple.second)
                b = b.coerceAtLeast(triple.third)
            }

            r * g * b
        }.toString()
    }
}

fun main() = Day02(
    Day02::class.java.getResource("/2023/day02/realInput1.txt")!!.readText()
).runBoth()
package org.example.e3fxgaming.adventOfCode.aoc2023.day02

import org.example.e3fxgaming.adventOfCode.utility.Day
import org.example.e3fxgaming.adventOfCode.utility.IndividualLineInputParser
import org.example.e3fxgaming.adventOfCode.utility.InputParser

class Day02(inputLines: String) : Day<List<Triple<Int, Int, Int>>, List<Triple<Int, Int, Int>>> {
    override val partOneParser: InputParser<List<Triple<Int, Int, Int>>> =
        object : IndividualLineInputParser<List<Triple<Int, Int, Int>>>(inputLines) {
            override fun parseLine(line: String): List<Triple<Int, Int, Int>> {
                return line.substringAfter(": ").split("; ").map { round ->
                    IntArray(3).also { rgb ->
                        round.split(", ").forEach { countAndColor ->
                            val (count, color) = countAndColor.split(" ")
                            when (color) {
                                "red" -> rgb[0] = count.toInt()
                                "green" -> rgb[1] = count.toInt()
                                "blue" -> rgb[2] = count.toInt()
                            }
                        }
                    }.let { tripleDesc ->
                        Triple(tripleDesc[0], tripleDesc[1], tripleDesc[2])
                    }
                }
            }
        }

    override val partTwoParser: InputParser<List<Triple<Int, Int, Int>>> = partOneParser


    private fun Triple<Int, Int, Int>.allowed() = first <= 12 && second <= 13 && third <= 14

    override fun solveFirst(given: List<List<Triple<Int, Int, Int>>>): String {
        return given.withIndex().fold(0) { acc, (index, gameRecording) ->
            if (gameRecording.any { !it.allowed() }) {
                return@fold acc
            }

            acc + (index + 1)
        }.toString()
    }

    override fun solveSecond(given: List<List<Triple<Int, Int, Int>>>): String {
        return given.sumOf { drawingRecordings ->
            var r = 0
            var g = 0
            var b = 0

            drawingRecordings.forEach { triple ->
                r = r.coerceAtLeast(triple.first)
                g = g.coerceAtLeast(triple.second)
                b = b.coerceAtLeast(triple.third)
            }

            r * g * b
        }.toString()
    }
}

fun main() = Day02(
    Day02::class.java.getResource("/2023/day02/realInput1.txt")!!.readText()
).runBoth()