71 lines
2.3 KiB
Kotlin

package aoc2023
import println
import readInput
import splitInts
/*
--- Day 4: Scratchcards ---
https://adventofcode.com/2023/day/4
*/
fun main() {
val inlineTestInput = """
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
"""
fun part1(input: List<String>): Int {
return input.map {
"Card +(\\d+): (.*)".toRegex().matchEntire(it)?.destructured
?.let { (id, game) ->
val (wins, numbers) = game.split(" | ")
val winSet = wins.splitInts().toSet()
val numberSet = numbers.splitInts().toSet()
val matches = winSet.intersect(numberSet)
1 shl (matches.size - 1)
}
}.sumOf { it!! }
}
fun part2(input: List<String>): Int {
val winTable = input.map {
"Card +(\\d+): (.*)".toRegex().matchEntire(it)?.destructured
?.let { (id, game) ->
val (wins, numbers) = game.split(" | ")
val winSet = wins.splitInts().toSet()
val numberSet = numbers.splitInts().toSet()
val matches = winSet.intersect(numberSet)
matches.size
}!!
}.toList()
val accTable = IntArray(winTable.size)
for (i in winTable.indices.reversed()) {
var sum = 1
for (j in i + 1 until (i + winTable[i] + 1).coerceAtMost(winTable.size)) {
sum += accTable[j]
}
accTable[i] = sum
}
return accTable.sum()
}
// test if implementation meets criteria from the description, like:
val testInput = inlineTestInput.trim().reader().readLines()
//val testInput = readInput("aoc2023/Day04_test")
val testInputPart1Result = part1(testInput)
println("Part 1 Test: $testInputPart1Result")
val testInputPart2Result = part2(testInput)
println("Part 2 Test: $testInputPart2Result")
check(testInputPart1Result == 13)
check(testInputPart2Result == 30)
val input = readInput("aoc2023/Day04")
part1(input).println()
part2(input).println()
}