1
+ package advent2023
2
+
3
+ import kotlin.math.pow
4
+
5
+ private const val CARD = " Card"
6
+ private const val COLON_SEPARATOR = " :"
7
+
8
+ class Day04 (private val input : List <String >) {
9
+
10
+ fun solvePart1 (): Int {
11
+ return input.sumOf { card ->
12
+ val matchCount = findMatchCountForCard(card)
13
+ 2.0 .pow(matchCount - 1 ).toInt()
14
+ }
15
+ }
16
+
17
+ fun solvePart2 (): Int {
18
+ val cardToTotalCount = mutableMapOf<Int , Int >()
19
+
20
+ val cardToMatchCount = input.map { card ->
21
+ val cardNumber = card.substringAfter(CARD )
22
+ .substringBefore(COLON_SEPARATOR )
23
+ .trim()
24
+ .toInt()
25
+ .also {
26
+ // init `cardToTotalCount` with each card occurring once
27
+ cardToTotalCount[it] = 1
28
+ }
29
+ cardNumber to findMatchCountForCard(card)
30
+ }
31
+
32
+ cardToMatchCount.forEach { (cardNumber, matchCount) ->
33
+ repeat(matchCount) {
34
+ cardToTotalCount[cardNumber + it + 1 ] =
35
+ checkNotNull(cardToTotalCount[cardNumber + it + 1 ]) + checkNotNull(cardToTotalCount[cardNumber])
36
+ }
37
+ }
38
+
39
+ return cardToTotalCount.map { it.value }.sum()
40
+ }
41
+
42
+ private fun findMatchCountForCard (cardInfo : String ): Int {
43
+ val numbers = cardInfo.split(" :" ).last().split(" |" )
44
+
45
+ val winningNumbers = numbers
46
+ .first()
47
+ .split(" " )
48
+ .filter { it.isNotEmpty() }
49
+ .map { it.trim() }
50
+ .map { it.toInt() }
51
+ val cardsInHand = numbers
52
+ .last()
53
+ .split(" " )
54
+ .filter { it.isNotEmpty() }
55
+ .map { it.trim() }
56
+ .map { it.toInt() }
57
+
58
+ var count = 0
59
+ cardsInHand.forEach { number ->
60
+ if (number in winningNumbers) {
61
+ count + = 1
62
+ }
63
+ }
64
+ return count
65
+ }
66
+ }
67
+
68
+ fun main () {
69
+ val input = Resources .resourceAsListOfString(" advent2023/day04.txt" )
70
+ val day04 = Day04 (input = input)
71
+ println (" Part 1 Solution: ${day04.solvePart1()} " )
72
+ println (" Part 2 Solution: ${day04.solvePart2()} " )
73
+ }
0 commit comments