-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDay07.kt
78 lines (65 loc) · 2.6 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
76
77
78
/*
* Copyright (c) 2023 by Todd Ginsberg
*/
/**
* Advent of Code 2023, Day 7 - Camel Cards
* Problem Description: http://adventofcode.com/2023/day/7
* Blog Post/Commentary: https://todd.ginsberg.com/post/advent-of-code/2023/day7/
*/
package com.ginsberg.advent2023
class Day07(private val input: List<String>) {
fun solvePart1(): Int =
playCamelCards()
fun solvePart2(): Int =
playCamelCards(true)
private fun playCamelCards(jokersWild: Boolean = false): Int =
input
.asSequence()
.map { row -> row.split(" ") }
.map { parts -> Hand(parts.first(), parts.last().toInt(), jokersWild) }
.sorted()
.mapIndexed { index, hand -> hand.bid * (index + 1) }
.sum()
private class Hand(cards: String, val bid: Int, jokersWild: Boolean) : Comparable<Hand> {
private val identity: Int = calculateIdentity(
cards,
if (jokersWild) STRENGTH_WITH_JOKERS else STRENGTH_WITHOUT_JOKERS,
if (jokersWild) this::calculateCategoryWithJokers else this::calculateCategoryWithoutJokers
)
private fun calculateIdentity(
cards: String,
strength: String,
categoryCalculation: (String) -> List<Int>
): Int {
val category = categoryCalculation(cards)
return cards.fold(CATEGORIES.indexOf(category)) { acc, card ->
(acc shl 4) or strength.indexOf(card)
}
}
private fun calculateCategoryWithoutJokers(cards: String): List<Int> =
cards.groupingBy { it }.eachCount().values.sortedDescending()
private fun calculateCategoryWithJokers(cards: String): List<Int> {
val cardsWithoutJokers = cards.filterNot { it == 'J' }
val numberOfJokers = cards.length - cardsWithoutJokers.length
return if (numberOfJokers == 5) listOf(5)
else calculateCategoryWithoutJokers(cardsWithoutJokers).toMutableList().apply {
this[0] += numberOfJokers
}
}
override fun compareTo(other: Hand): Int =
this.identity - other.identity
companion object {
private val CATEGORIES = listOf(
listOf(1, 1, 1, 1, 1),
listOf(2, 1, 1, 1),
listOf(2, 2, 1),
listOf(3, 1, 1),
listOf(3, 2),
listOf(4, 1),
listOf(5)
)
private const val STRENGTH_WITHOUT_JOKERS = "23456789TJQKA"
private const val STRENGTH_WITH_JOKERS = "J23456789TQKA"
}
}
}