generated from Jadarma/advent-of-code-kotlin-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Y2023D02.kt
67 lines (56 loc) · 2.75 KB
/
Y2023D02.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
package aockt.y2023
import io.github.jadarma.aockt.core.Solution
object Y2023D02 : Solution {
/**
* Holds observations for one instance of the elf's game.
* @property id The ID of the game.
* @property rounds The color-count of the balls revealed during the game.
*/
private data class Game(val id: Int, val rounds: List<Balls>) {
/** A set of balls, associated by their color. */
data class Balls(val red: Int, val green: Int, val blue: Int) {
val power: Int get() = red * green * blue
}
/** Whether the game's [rounds] could have been played with a [set] of this dimension. */
fun isPossibleWith(set: Balls): Boolean = rounds.all {
it.red <= set.red && it.green <= set.green && it.blue <= set.blue
}
/** The smallest set of balls required to play the [rounds] of this game successfully. */
fun minimumSet(): Balls = Balls(
red = rounds.maxOf { it.red },
green = rounds.maxOf { it.green },
blue = rounds.maxOf { it.blue },
)
companion object {
/** Attempt to parse a [Game] notation from the [input] line. */
fun parse(input: String): Game = runCatching {
Game(
id = input.substringBefore(": ").substringAfter("Game ").toInt(),
rounds = input
.substringAfter(": ")
.split("; ")
.map { round ->
round
.split(", ", limit = 3)
.filterNot(String::isEmpty)
.map { it.split(" ", limit = 2) }
.associate { (count, color) -> color to count.toInt() }
.run {
Balls(
red = getOrDefault("red", 0),
green = getOrDefault("green", 0),
blue = getOrDefault("blue", 0),
)
}
},
)
}.getOrElse { cause -> throw IllegalArgumentException("Invalid input.", cause) }
}
}
/** Parse the [input] and return the list of [Game]s the elf played. */
private fun parseInput(input: String): Sequence<Game> = input.lineSequence().map(Game.Companion::parse)
override fun partOne(input: String) = parseInput(input)
.filter { game -> game.isPossibleWith(Game.Balls(red = 12, green = 13, blue = 14)) }
.sumOf { it.id }
override fun partTwo(input: String) = parseInput(input).sumOf { game -> game.minimumSet().power }
}