package aoc2023

import println
import readInput

/*
--- Day 15: Lens Library ---
https://adventofcode.com/2023/day/15
*/
fun main() {

    val inlineTestInput = """
rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7
"""

    fun hash(str: String): Int = str.map { it.code }.fold(0) { acc, c -> ((acc + c) * 17) and 0xff }
    fun part1(input: List<String>): Int {
        return input.first().split(",").sumOf { hash(it) }
    }

    fun part2(input: List<String>): Int {
        val boxes = Array<MutableMap<String, Int>>(256) { LinkedHashMap() }
        input.first().split(",").forEach { it ->
            if (it.contains('=')) {
                val (label, value) = it.split("=")
                boxes[hash(label)][label] = value.toInt()
            } else {
                val label = it.removeSuffix("-")
                boxes[hash(label)].remove(label)
            }
        }
        return boxes.mapIndexed { boxno, contents ->
            contents.map { entry -> entry.value }
                .mapIndexed { index, value -> (boxno + 1) * value * (index + 1) }.sum()
        }.sum()
    }

    // test if implementation meets criteria from the description, like:
    val testInput = inlineTestInput.trim().reader().readLines()
    //val testInput = readInput("aoc2023/Day15_test")
    val testInputPart1Result = part1(testInput)
    println("Part 1 Test: $testInputPart1Result")
    val testInputPart2Result = part2(testInput)
    println("Part 2 Test: $testInputPart2Result")
    check(testInputPart1Result == 1320)
    check(testInputPart2Result == 145)

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