import kotlin.IllegalArgumentException

fun main() {

    fun valueForChar(char: Char): Int {
        return when (char) {
            'a' -> 1
            'b' -> 2
            'c' -> 3
            'd' -> 4
            'e' -> 5
            'f' -> 6
            'g' -> 7
            'h' -> 8
            'i' -> 9
            'j' -> 10
            'k' -> 11
            'l' -> 12
            'm' -> 13
            'n' -> 14
            'o' -> 15
            'p' -> 16
            'q' -> 17
            'r' -> 18
            's' -> 19
            't' -> 20
            'u' -> 21
            'v' -> 22
            'w' -> 23
            'x' -> 24
            'y' -> 25
            'z' -> 26
            'A' -> 27
            'B' -> 28
            'C' -> 29
            'D' -> 30
            'E' -> 31
            'F' -> 32
            'G' -> 33
            'H' -> 34
            'I' -> 35
            'J' -> 36
            'K' -> 37
            'L' -> 38
            'M' -> 39
            'N' -> 40
            'O' -> 41
            'P' -> 42
            'Q' -> 43
            'R' -> 44
            'S' -> 45
            'T' -> 46
            'U' -> 47
            'V' -> 48
            'W' -> 49
            'X' -> 50
            'Y' -> 51
            'Z' -> 52
            else -> throw IllegalArgumentException()
        }
    }

    fun findMatchingChar(s1: String, s2: String): Char {
        var x = '0'
        s1.forEach {
            c -> if (s2.contains(c)) x = c
        }
        return x
    }

    fun findMatchingCharBetween(s1: String, s2: String, s3: String): Char {
        var x = '0'
        s1.forEach {
            c -> if (s2.contains(c) && s3.contains(c)) x = c
        }
        return x
    }

    fun String.splitInHalf() = take(this.length / 2) to substring(this.length / 2)

    fun part2(input: List<String>): Int {
        return input.chunked(3).map { findMatchingCharBetween(it[0], it[1], it[2]) }.sumOf { valueForChar(it)}
    }

    fun part1(input: List<String>): Int {
        return input.map { t -> t.splitInHalf() }
            .map { findMatchingChar(it.first, it.second) }
            .sumOf { valueForChar(it) }
    }

    // test if implementation meets criteria from the description, like:
    val testInput = readInput("Day03_test")
    check(part1(testInput) == 157)
    check(part2(testInput) == 70)

    val input = readInput("Day03")
    println(part1(input))
    println(part2(input))
}

import kotlin.IllegalArgumentException

fun main() {

    fun valueForChar(char: Char): Int {
        return when (char) {
            'a' -> 1
            'b' -> 2
            'c' -> 3
            'd' -> 4
            'e' -> 5
            'f' -> 6
            'g' -> 7
            'h' -> 8
            'i' -> 9
            'j' -> 10
            'k' -> 11
            'l' -> 12
            'm' -> 13
            'n' -> 14
            'o' -> 15
            'p' -> 16
            'q' -> 17
            'r' -> 18
            's' -> 19
            't' -> 20
            'u' -> 21
            'v' -> 22
            'w' -> 23
            'x' -> 24
            'y' -> 25
            'z' -> 26
            'A' -> 27
            'B' -> 28
            'C' -> 29
            'D' -> 30
            'E' -> 31
            'F' -> 32
            'G' -> 33
            'H' -> 34
            'I' -> 35
            'J' -> 36
            'K' -> 37
            'L' -> 38
            'M' -> 39
            'N' -> 40
            'O' -> 41
            'P' -> 42
            'Q' -> 43
            'R' -> 44
            'S' -> 45
            'T' -> 46
            'U' -> 47
            'V' -> 48
            'W' -> 49
            'X' -> 50
            'Y' -> 51
            'Z' -> 52
            else -> throw IllegalArgumentException()
        }
    }

    fun findMatchingChar(s1: String, s2: String): Char {
        var x = '0'
        s1.forEach {
            c -> if (s2.contains(c)) x = c
        }
        return x
    }

    fun findMatchingCharBetween(s1: String, s2: String, s3: String): Char {
        var x = '0'
        s1.forEach {
            c -> if (s2.contains(c) && s3.contains(c)) x = c
        }
        return x
    }

    fun String.splitInHalf() = take(this.length / 2) to substring(this.length / 2)

    fun part2(input: List<String>): Int {
        return input.chunked(3).map { findMatchingCharBetween(it[0], it[1], it[2]) }.sumOf { valueForChar(it)}
    }

    fun part1(input: List<String>): Int {
        return input.map { t -> t.splitInHalf() }
            .map { findMatchingChar(it.first, it.second) }
            .sumOf { valueForChar(it) }
    }

    // test if implementation meets criteria from the description, like:
    val testInput = readInput("Day03_test")
    check(part1(testInput) == 157)
    check(part2(testInput) == 70)

    val input = readInput("Day03")
    println(part1(input))
    println(part2(input))
}
