Skip to content

Commit 5baaf42

Browse files
committed
Solved day07 part 2
1 parent c700c88 commit 5baaf42

File tree

9 files changed

+152
-56
lines changed

9 files changed

+152
-56
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44

55
// project meta data
66
group 'de.havox_design.aoc2023'
7-
version '0.6.2'
7+
version '0.6.4'
88

99
// Switch to gradle "all" distribution.
1010
wrapper {

day07/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,33 @@ with its rank (`765` * 1 + `220` * 2 + `28` * 3 + `684` * 4 + `483` * 5). So the
7878
**`6440`**.
7979

8080
Find the rank of every hand in your set. **What are the total winnings**?
81+
82+
# Part Two
83+
To make things a little more interesting, the Elf introduces one additional rule. Now, `J` cards are
84+
[jokers](https://en.wikipedia.org/wiki/Joker_(playing_card)) - wildcards that can act like whatever card would make the
85+
hand the strongest type possible.
86+
87+
To balance this, **`J` cards are now the weakest** individual cards, weaker even than `2`. The other cards stay in the
88+
same order: `A`, `K`, `Q`, `T`, `9`, `8`, `7`, `6`, `5`, `4`, `3`, `2`, `J`.
89+
90+
`J` cards can pretend to be whatever card is best for the purpose of determining hand type; for example, `QJJQ2` is now
91+
considered **four of a kind**. However, for the purpose of breaking ties between two hands of the same type, `J` is
92+
always treated as `J`, not the card it's pretending to be: `JKKK2` is weaker than `QQQQ2` because `J` is weaker than
93+
`Q`.
94+
95+
Now, the above example goes very differently:
96+
```
97+
32T3K 765
98+
T55J5 684
99+
KK677 28
100+
KTJJT 220
101+
QQQJA 483
102+
```
103+
* `32T3K` is still the only **one pair**; it doesn't contain any jokers, so its strength doesn't increase.
104+
* `KK677` is now the only two pair, making it the second-weakest hand.
105+
* `T55J5`, `KTJJT`, and `QQQJA` are now all **four of a kind**! `T55J5` gets rank `3`, `QQQJA` gets rank `4`, and
106+
`KTJJT` gets rank `5`.
107+
108+
With the new joker rule, the total winnings in this example are **`5905`**.
109+
110+
Using the new joker rule, find the rank of every hand in your set. **What are the new total winnings**?
Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,36 @@
11
package de.havox_design.aoc2023.day07
22

3-
enum class Card(val symbol: Char, private val order: Int) {
4-
TWO('2', 2),
5-
THREE('3', 3),
6-
FOUR('4', 4),
7-
FIVE('5', 5),
8-
SIX('6', 6),
9-
SEVEN('7', 7),
10-
EIGHT('8', 8),
11-
NINE('9', 9),
12-
TEN('T', 10),
13-
JOKER('J', 11),
14-
QUEEN('Q', 12),
15-
KING('K', 13),
16-
ACE('A', 14);
3+
enum class Card(val symbol: Char, private val orderPartOne: Int, private val orderPartTwo: Int) {
4+
TWO('2', 2, 2),
5+
THREE('3', 3, 3),
6+
FOUR('4', 4, 4),
7+
FIVE('5', 5, 5),
8+
SIX('6', 6, 6),
9+
SEVEN('7', 7, 7),
10+
EIGHT('8', 8, 8),
11+
NINE('9', 9, 9),
12+
TEN('T', 10, 10),
13+
JOKER('J', 11, 1),
14+
QUEEN('Q', 12, 12),
15+
KING('K', 13, 13),
16+
ACE('A', 14, 14);
1717

1818
companion object {
1919
fun from(c: Char): Card {
2020
if (entries.map { card -> card.symbol }.contains(c)) {
21-
return entries.first { card -> card.symbol == c }
21+
return entries
22+
.first { card -> card.symbol == c }
2223
}
2324

2425
throw IllegalArgumentException("No knows card symbol '${c}'")
2526
}
2627

27-
fun compare(a: Card, b: Card): Int =
28-
a.order.compareTo(b.order)
28+
fun compare(a: Card, b: Card, partOne: Boolean): Int {
29+
if (partOne) {
30+
return a.orderPartOne.compareTo(b.orderPartOne)
31+
}
32+
33+
return a.orderPartTwo.compareTo(b.orderPartTwo)
34+
}
2935
}
3036
}

day07/src/main/kotlin/de/havox_design/aoc2023/day07/Day07.kt

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,31 @@ package de.havox_design.aoc2023.day07
33
class Day07(private var filename: String) {
44
private val ELEMENT_DELIMITER = " "
55

6-
fun solvePart1(): Long {
7-
val data = mapInput(getResourceAsText(filename))
8-
val sortedData = data.sortedBy { game -> game.first }.toList()
6+
fun solvePart1(): Long =
7+
process(true)
8+
9+
fun solvePart2(): Long =
10+
process(false)
11+
12+
private fun process(isPartOne: Boolean): Long {
13+
val data = mapInput(getResourceAsText(filename), isPartOne)
14+
val sortedData = data
15+
.sortedBy { game -> game.first }
16+
.toList()
917
var winnings = 0L
1018

11-
for(index in sortedData.indices) {
19+
for (index in sortedData.indices) {
1220
winnings += (index + 1) * sortedData[index].second
1321
}
1422

1523
return winnings
1624
}
1725

18-
fun solvePart2(): Long =
19-
0L
20-
21-
private fun mapInput(input: List<String>):List<Pair<Hand,Int>> =
26+
private fun mapInput(input: List<String>, isPartOne: Boolean): List<Pair<Hand, Int>> =
2227
input
2328
.map { row ->
2429
val elements = row.split(ELEMENT_DELIMITER)
25-
val hand = Hand.from(elements[0])
30+
val hand = Hand.from(elements[0], isPartOne)
2631
val bit = elements[1].toInt()
2732

2833
return@map Pair(hand, bit)

day07/src/main/kotlin/de/havox_design/aoc2023/day07/GameType.kt

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,46 +10,101 @@ enum class GameType(private var order: Int) {
1010
HIGH_CARD(0);
1111

1212
companion object {
13-
fun from(hand: Hand): GameType {
13+
fun from(hand: Hand, isPartOne: Boolean): GameType {
14+
if (isPartOne) {
15+
return fromPartOne(hand)
16+
}
17+
18+
return fromPartTwo(hand)
19+
}
20+
21+
fun compare(a: GameType, b: GameType): Int =
22+
a.order.compareTo(b.order)
23+
24+
private fun fromPartOne(hand: Hand): GameType {
1425
val cardMap = getCardMap(hand)
1526

16-
if(cardMap.size == 1) {
27+
if (cardMap.size == 1) {
1728
return FIVE_OF_A_KIND
1829
}
19-
if(cardMap.size == 2) {
20-
if(cardMap.values.max() == 4) {
30+
if (cardMap.size == 2) {
31+
if (cardMap.values.max() == 4) {
2132
return FOUR_OF_A_KIND
2233
}
2334
return FULL_HOUSE
2435
}
25-
if(cardMap.size == 3) {
26-
if(cardMap.values.max() == 3) {
36+
if (cardMap.size == 3) {
37+
if (cardMap.values.max() == 3) {
2738
return THREE_OF_A_KIND
2839
}
2940
return TWO_PAIRS
3041
}
31-
if(cardMap.values.max() == 2) {
42+
if (cardMap.values.max() == 2) {
3243
return ONE_PAIR
3344
}
3445
return HIGH_CARD
3546
}
3647

37-
fun compare(a: GameType, b: GameType): Int =
38-
a.order.compareTo(b.order)
48+
private fun fromPartTwo(hand: Hand): GameType {
49+
val numberOfJokers = getNumberOfJokers(hand)
50+
51+
if (numberOfJokers == 0) {
52+
return fromPartOne(hand)
53+
}
54+
55+
val cardMap = getCardMap(hand)
56+
.filter { entry -> entry.key != Card.JOKER }
57+
58+
59+
if (numberOfJokers == 5 || cardMap.values.max() + numberOfJokers == 5) {
60+
return FIVE_OF_A_KIND
61+
}
62+
if (cardMap.values.max() + numberOfJokers == 4) {
63+
return FOUR_OF_A_KIND
64+
}
65+
if (cardMap.values.max() + numberOfJokers >= 3) {
66+
if (cardMap.size == 2 && numberOfJokers <= 1) {
67+
return FULL_HOUSE
68+
}
69+
70+
return THREE_OF_A_KIND
71+
}
72+
if (cardMap.values.max() == 2 && numberOfJokers == 1) {
73+
return TWO_PAIRS
74+
}
75+
76+
if (numberOfJokers == 1) {
77+
return ONE_PAIR
78+
}
79+
80+
return HIGH_CARD
81+
}
3982

83+
@SuppressWarnings("kotlin:S6611")
4084
private fun getCardMap(hand: Hand): Map<Card, Int> {
4185
val result = HashMap<Card, Int>()
4286

43-
for(c in hand.cards) {
44-
if(result.containsKey(c)) {
87+
for (c in hand.cards) {
88+
if (result.containsKey(c)) {
4589
result[c] = result[c]!! + 1
46-
}
47-
else {
90+
} else {
4891
result[c] = 1
4992
}
5093
}
5194

5295
return result
5396
}
97+
98+
private fun getNumberOfJokers(hand: Hand): Int {
99+
var numberOfJokers = 0
100+
101+
for (c in hand.cards) {
102+
if (c == Card.JOKER) {
103+
numberOfJokers++
104+
}
105+
}
106+
107+
return numberOfJokers
108+
}
54109
}
55110
}

day07/src/main/kotlin/de/havox_design/aoc2023/day07/Hand.kt

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
package de.havox_design.aoc2023.day07
22

3-
class Hand(val cards: List<Card>): Comparable<Hand> {
3+
class Hand(val cards: List<Card>, private val isPartOne: Boolean) : Comparable<Hand> {
44
override fun compareTo(other: Hand): Int =
5-
compare(this, other)
5+
compare(this, other, isPartOne)
66

7-
companion object{
8-
fun from(input: String): Hand {
7+
companion object {
8+
fun from(input: String, isPartOne: Boolean): Hand {
99
val hand = ArrayList<Card>()
1010

11-
for(c in input.toCharArray()) {
11+
for (c in input.toCharArray()) {
1212
hand.add(Card.from(c))
1313
}
1414

15-
return Hand(hand)
15+
return Hand(hand, isPartOne)
1616
}
1717

18-
fun compare(a: Hand, b: Hand): Int {
19-
if(a == b) {
18+
fun compare(a: Hand, b: Hand, isPartOne: Boolean): Int {
19+
if (a == b) {
2020
return 0
2121
}
2222

23-
val aGameType = GameType.from(a)
24-
val bGameType = GameType.from(b)
23+
val aGameType = GameType.from(a, isPartOne)
24+
val bGameType = GameType.from(b, isPartOne)
2525

26-
if(aGameType == bGameType) {
27-
for(index in a.cards.indices) {
28-
if(a.cards[index] == b.cards[index]) {
26+
if (aGameType == bGameType) {
27+
for (index in a.cards.indices) {
28+
if (a.cards[index] == b.cards[index]) {
2929
continue
3030
}
3131

32-
return Card.compare(a.cards[index], b.cards[index])
32+
return Card.compare(a.cards[index], b.cards[index], isPartOne)
3333
}
3434
}
3535

day07/src/test/kotlin/de/havox_design/aoc2023/day07/Day07Test.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ class Day07Test {
2727
@JvmStatic
2828
private fun getDataForTestSolvePart1(): Stream<Arguments> =
2929
Stream.of(
30-
Arguments.of("part1sample.txt", 6440L)
30+
Arguments.of("sample.txt", 6440L)
3131
)
3232

3333
@JvmStatic
3434
private fun getDataForTestSolvePart2(): Stream<Arguments> =
3535
Stream.of(
36-
Arguments.of("part2sample1.txt", 0L)
36+
Arguments.of("sample.txt", 5905L)
3737
)
3838
}
3939
}

day07/src/test/resources/part2sample1.txt

Whitespace-only changes.

0 commit comments

Comments
 (0)