-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day07.kt
75 lines (61 loc) · 2.62 KB
/
Day07.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package io.dmitrijs.aoc2023
import io.dmitrijs.aoc2023.Day07.Type.FIVE_OF_A_KIND
import io.dmitrijs.aoc2023.Day07.Type.FOUR_OF_A_KIND
import io.dmitrijs.aoc2023.Day07.Type.FULL_HOUSE
import io.dmitrijs.aoc2023.Day07.Type.HIGH_CARD
import io.dmitrijs.aoc2023.Day07.Type.ONE_PAIR
import io.dmitrijs.aoc2023.Day07.Type.THREE_OF_A_KIND
import io.dmitrijs.aoc2023.Day07.Type.TWO_PAIR
class Day07(private val input: List<String>) {
fun puzzle1() = solve("AKQJT98765432")
fun puzzle2() = solve("AKQT98765432J")
private fun solve(deck: String): Long {
val hands = input
.map { line ->
val cards = line.substringBefore(" ")
val score = line.substringAfter(" ").toLong()
recognize(cards, deck) to score
}.sortedBy { it.first }
// Smallest first
return hands.withIndex().sumOf { (index, hand) -> (index + 1) * hand.second }
}
private fun recognize(cards: String, deck: String): Hand {
val joker = deck.last() == JOKER
val count = deck.map { card -> cards.count { (!joker && card == it) || (joker && card == it && card != JOKER) } }
.sortedDescending()
.toMutableList()
// Jokers go to the strongest position.
if (joker) count[0] += cards.count { it == JOKER }
val one = count[0]
val two = count[1]
return Hand(cards, deck) {
when {
one == 5 -> FIVE_OF_A_KIND
one == 4 -> FOUR_OF_A_KIND
one == 3 && two == 2 -> FULL_HOUSE
one == 3 -> THREE_OF_A_KIND
one == 2 && two == 2 -> TWO_PAIR
one == 2 -> ONE_PAIR
else -> HIGH_CARD
}
}
}
private enum class Type { FIVE_OF_A_KIND, FOUR_OF_A_KIND, FULL_HOUSE, THREE_OF_A_KIND, TWO_PAIR, ONE_PAIR, HIGH_CARD }
private data class Hand(private val type: Type, private val deck: String, private val cards: String) : Comparable<Hand> {
constructor(cards: String, deck: String, type: () -> Type) : this(type(), deck, cards)
private val rank get() = Type.entries.indexOf(type)
override fun compareTo(other: Hand) =
if (rank - other.rank != 0) {
other.rank - rank
} else {
(0..4).firstNotNullOfOrNull { index ->
val a = deck.indexOf(cards[index])
val b = deck.indexOf(other.cards[index])
if (a != b) b - a else null
} ?: error("Invalid card comparison.")
}
}
companion object {
private const val JOKER = 'J'
}
}