Refactor day 2 of AoC 2023
This commit is contained in:
parent
fa27aa2405
commit
8a9f518b5b
12 changed files with 248 additions and 119 deletions
42
advent-of-code/2023/day_02/.gitignore
vendored
Normal file
42
advent-of-code/2023/day_02/.gitignore
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
.gradle
|
||||||
|
gradle
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
out/
|
||||||
|
!**/src/main/**/out/
|
||||||
|
!**/src/test/**/out/
|
||||||
|
|
||||||
|
### Kotlin ###
|
||||||
|
.kotlin
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
bin/
|
||||||
|
!**/src/main/**/bin/
|
||||||
|
!**/src/test/**/bin/
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
81
advent-of-code/2023/day_02/README.md
Normal file
81
advent-of-code/2023/day_02/README.md
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
# Advent of Code 2023 day 2 solution in Kotlin
|
||||||
|
|
||||||
|
## Cube Conundrum
|
||||||
|
|
||||||
|
[Task page](https://adventofcode.com/2023/day/2)
|
||||||
|
|
||||||
|
You're launched high into the atmosphere! The apex of your trajectory just barely reaches the surface of a
|
||||||
|
large island floating in the sky. You gently land in a fluffy pile of leaves.
|
||||||
|
It's quite cold, but you don't see much snow. An Elf runs over to greet you.
|
||||||
|
|
||||||
|
The Elf explains that you've arrived at Snow Island and apologizes for the lack of snow.
|
||||||
|
He'll be happy to explain the situation, but it's a bit of a walk, so you have some time.
|
||||||
|
They don't get many visitors up here; would you like to play a game in the meantime?
|
||||||
|
|
||||||
|
As you walk, the Elf shows you a small bag and some cubes which are either red, green, or blue.
|
||||||
|
Each time you play this game, he will hide a secret number of cubes of each color in the bag,
|
||||||
|
and your goal is to figure out information about the number of cubes.
|
||||||
|
|
||||||
|
To get information, once a bag has been loaded with cubes, the Elf will reach into the bag,
|
||||||
|
grab a handful of random cubes, show them to you, and then put them back in the bag. He'll do this a few times per game.
|
||||||
|
|
||||||
|
You play several games and record the information from each game (your puzzle input).
|
||||||
|
Each game is listed with its ID number (like the 11 in Game 11: ...) followed by a semicolon-separated
|
||||||
|
list of subsets of cubes that were revealed from the bag (like 3 red, 5 green, 4 blue).
|
||||||
|
|
||||||
|
For example, the record of a few games might look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
|
||||||
|
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
|
||||||
|
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
|
||||||
|
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
|
||||||
|
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
|
||||||
|
```
|
||||||
|
|
||||||
|
In game 1, three sets of cubes are revealed from the bag (and then put back again).
|
||||||
|
The first set is 3 blue cubes and 4 red cubes; the second set is 1 red cube, 2 green cubes, and 6 blue cubes;
|
||||||
|
the third set is only 2 green cubes.
|
||||||
|
|
||||||
|
The Elf would first like to know which games would have been possible if the bag contained only 12 red cubes,
|
||||||
|
13 green cubes, and 14 blue cubes?
|
||||||
|
|
||||||
|
In the example above, games 1, 2, and 5 would have been possible if the bag had been loaded with that configuration.
|
||||||
|
However, game 3 would have been impossible because at one point the Elf showed you 20 red cubes at once; similarly,
|
||||||
|
game 4 would also have been impossible because the Elf showed you 15 blue cubes at once.
|
||||||
|
If you add up the IDs of the games that would have been possible, you get 8.
|
||||||
|
|
||||||
|
Determine which games would have been possible if the bag had been loaded with only 12 red cubes, 13 green cubes,
|
||||||
|
and 14 blue cubes. What is the sum of the IDs of those games?
|
||||||
|
|
||||||
|
|
||||||
|
## Part Two
|
||||||
|
|
||||||
|
The Elf says they've stopped producing snow because they aren't getting any water!
|
||||||
|
He isn't sure why the water stopped; however, he can show you how to get to the water source
|
||||||
|
to check it out for yourself. It's just up ahead!
|
||||||
|
|
||||||
|
As you continue your walk, the Elf poses a second question: in each game you played,
|
||||||
|
what is the fewest number of cubes of each color that could have been in the bag to make the game possible?
|
||||||
|
|
||||||
|
Again consider the example games from earlier:
|
||||||
|
|
||||||
|
```
|
||||||
|
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
|
||||||
|
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
|
||||||
|
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
|
||||||
|
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
|
||||||
|
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
|
||||||
|
```
|
||||||
|
|
||||||
|
- In game 1, the game could have been played with as few as 4 red, 2 green, and 6 blue cubes. If any color had even one fewer cube, the game would have been impossible.
|
||||||
|
- Game 2 could have been played with a minimum of 1 red, 3 green, and 4 blue cubes.
|
||||||
|
- Game 3 must have been played with at least 20 red, 13 green, and 6 blue cubes.
|
||||||
|
- Game 4 required at least 14 red, 3 green, and 15 blue cubes.
|
||||||
|
- Game 5 needed no fewer than 6 red, 3 green, and 2 blue cubes in the bag.
|
||||||
|
|
||||||
|
The power of a set of cubes is equal to the numbers of red, green, and blue cubes multiplied together.
|
||||||
|
The power of the minimum set of cubes in game 1 is 48. In games 2-5 it was 12, 1560, 630, and 36, respectively.
|
||||||
|
Adding up these five powers produces the sum 2286.
|
||||||
|
|
||||||
|
For each game, find the minimum set of cubes that must have been present. What is the sum of the power of these sets?
|
18
advent-of-code/2023/day_02/build.gradle.kts
Normal file
18
advent-of-code/2023/day_02/build.gradle.kts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "2.0.21"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "space.comfycamp"
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation(kotlin("test"))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
1
advent-of-code/2023/day_02/gradle.properties
Normal file
1
advent-of-code/2023/day_02/gradle.properties
Normal file
|
@ -0,0 +1 @@
|
||||||
|
kotlin.code.style=official
|
2
advent-of-code/2023/day_02/settings.gradle.kts
Normal file
2
advent-of-code/2023/day_02/settings.gradle.kts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
rootProject.name = "day_02"
|
||||||
|
|
61
advent-of-code/2023/day_02/src/main/kotlin/GameHost.kt
Normal file
61
advent-of-code/2023/day_02/src/main/kotlin/GameHost.kt
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package space.comfycamp
|
||||||
|
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
|
data class CubeSet(var red: Int, var green: Int, var blue: Int)
|
||||||
|
|
||||||
|
// Part 1
|
||||||
|
fun getSumOfCorrectGameIDs(text: List<String>): Int {
|
||||||
|
val games = readGames(text)
|
||||||
|
|
||||||
|
return games
|
||||||
|
.withIndex()
|
||||||
|
.filter{ el -> isGameValid(el.value) }
|
||||||
|
.sumOf { el -> el.index + 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isGameValid(cubeSets: List<CubeSet>): Boolean {
|
||||||
|
for (cubeSet in cubeSets) {
|
||||||
|
if (cubeSet.red > 12 || cubeSet.green > 13 || cubeSet.blue > 14) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Part 2
|
||||||
|
fun getSumOfPowers(text: List<String>): Int {
|
||||||
|
val games = readGames(text)
|
||||||
|
|
||||||
|
return games
|
||||||
|
.map { game ->
|
||||||
|
game.reduce { acc, cubeSet ->
|
||||||
|
CubeSet(
|
||||||
|
max(acc.red, cubeSet.red),
|
||||||
|
max(acc.green, cubeSet.green),
|
||||||
|
max(acc.blue, cubeSet.blue)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sumOf { cubeSet -> cubeSet.red * cubeSet.green * cubeSet.blue }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun readGames(text: List<String>): List<List<CubeSet>> {
|
||||||
|
return text
|
||||||
|
.map{ line -> line.split(": ")[1] }
|
||||||
|
.map{ sets -> sets.split("; ").map{ cubeSet -> parseCubeSet(cubeSet) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseCubeSet(description: String): CubeSet {
|
||||||
|
val cubeSet = CubeSet(0,0,0)
|
||||||
|
for (cubeStr in description.split(", ")) {
|
||||||
|
val (cubeCountStr, color) = cubeStr.split(" ")
|
||||||
|
when (color) {
|
||||||
|
"blue" -> cubeSet.blue = cubeCountStr.toInt()
|
||||||
|
"red" -> cubeSet.red = cubeCountStr.toInt()
|
||||||
|
"green" -> cubeSet.green = cubeCountStr.toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cubeSet
|
||||||
|
}
|
12
advent-of-code/2023/day_02/src/main/kotlin/Main.kt
Normal file
12
advent-of-code/2023/day_02/src/main/kotlin/Main.kt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package space.comfycamp
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val resource = object{}.javaClass.getResource("/input.txt")!!
|
||||||
|
val lines = resource.readText().trim().lines()
|
||||||
|
|
||||||
|
val res1 = getSumOfCorrectGameIDs(lines)
|
||||||
|
println("Part 1: $res1")
|
||||||
|
|
||||||
|
val res2 = getSumOfPowers(lines)
|
||||||
|
println("Part 2: $res2")
|
||||||
|
}
|
30
advent-of-code/2023/day_02/src/test/kotlin/GameHostTest.kt
Normal file
30
advent-of-code/2023/day_02/src/test/kotlin/GameHostTest.kt
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import space.comfycamp.getSumOfCorrectGameIDs
|
||||||
|
import space.comfycamp.getSumOfPowers
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
class GameHostTest {
|
||||||
|
@Test
|
||||||
|
fun testGetSumOfCorrectGameIDs() {
|
||||||
|
val lines = listOf(
|
||||||
|
"Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green",
|
||||||
|
"Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue",
|
||||||
|
"Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red",
|
||||||
|
"Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red",
|
||||||
|
"Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"
|
||||||
|
)
|
||||||
|
assertEquals(8, getSumOfCorrectGameIDs(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetSumOfPowers() {
|
||||||
|
val lines = listOf(
|
||||||
|
"Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green",
|
||||||
|
"Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue",
|
||||||
|
"Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red",
|
||||||
|
"Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red",
|
||||||
|
"Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"
|
||||||
|
)
|
||||||
|
assertEquals(2286, getSumOfPowers(lines))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,81 +0,0 @@
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
class CubeCount(var red: Int, var green: Int, var blue: Int) {
|
|
||||||
fun lessOrEqualThan(other: CubeCount): Boolean {
|
|
||||||
return red <= other.red && green <= other.green && blue <= other.blue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Solution02 {
|
|
||||||
// Part 1
|
|
||||||
fun getSumOfCorrectGameIDs(text: List<String>, cubes: CubeCount): Int {
|
|
||||||
val games = readGames(text)
|
|
||||||
var sum = 0
|
|
||||||
|
|
||||||
for (game in games.entries) {
|
|
||||||
var valid = true
|
|
||||||
|
|
||||||
for (count in game.value) {
|
|
||||||
if (!count.lessOrEqualThan(cubes)) {
|
|
||||||
valid = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valid) {
|
|
||||||
sum += game.key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sum
|
|
||||||
}
|
|
||||||
|
|
||||||
// Part 2
|
|
||||||
fun getSumOfPowers(text: List<String>): Int {
|
|
||||||
val games = readGames(text)
|
|
||||||
var sum = 0
|
|
||||||
|
|
||||||
for (game in games.values) {
|
|
||||||
var maxRed = 0
|
|
||||||
var maxGreen = 0
|
|
||||||
var maxBlue = 0
|
|
||||||
|
|
||||||
for (gameSet in game) {
|
|
||||||
maxRed = max(maxRed, gameSet.red)
|
|
||||||
maxGreen = max(maxGreen, gameSet.green)
|
|
||||||
maxBlue = max(maxBlue, gameSet.blue)
|
|
||||||
}
|
|
||||||
|
|
||||||
sum += maxRed * maxGreen * maxBlue
|
|
||||||
}
|
|
||||||
|
|
||||||
return sum
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun readGames(text: List<String>): HashMap<Int, MutableList<CubeCount>> {
|
|
||||||
val games = hashMapOf<Int, MutableList<CubeCount>>()
|
|
||||||
|
|
||||||
text.forEach {
|
|
||||||
// `it` example: "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green"
|
|
||||||
val (game, sets) = it.split(": ")
|
|
||||||
val gameID = game.split(" ")[1].toInt()
|
|
||||||
games[gameID] = arrayListOf()
|
|
||||||
|
|
||||||
// setStr example: "3 blue, 4 red"
|
|
||||||
for (setStr in sets.split("; ")) {
|
|
||||||
val gameSet = CubeCount(0,0,0)
|
|
||||||
// cubeStr example: "3 blue"
|
|
||||||
for (cubeStr in setStr.split(", ")) {
|
|
||||||
val (cubeCountStr, color) = cubeStr.split(" ")
|
|
||||||
when (color) {
|
|
||||||
"blue" -> gameSet.blue = cubeCountStr.toInt()
|
|
||||||
"red" -> gameSet.red = cubeCountStr.toInt()
|
|
||||||
"green" -> gameSet.green = cubeCountStr.toInt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
games[gameID]?.add(gameSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return games
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
|
|
||||||
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
|
|
||||||
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
|
|
||||||
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
|
|
||||||
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
|
|
|
@ -1,32 +0,0 @@
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class Solution02Test {
|
|
||||||
@Test
|
|
||||||
fun testGetSumOfCorrectGameIDs() {
|
|
||||||
val text = ResourceReader().readFile("day-02/test.txt")
|
|
||||||
val res = Solution02().getSumOfCorrectGameIDs(text, CubeCount(12, 13, 14))
|
|
||||||
assertEquals(8, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testGetPowerSum() {
|
|
||||||
val text = ResourceReader().readFile("day-02/test.txt")
|
|
||||||
val res = Solution02().getSumOfPowers(text)
|
|
||||||
assertEquals(2286, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun solvePart1() {
|
|
||||||
val text = ResourceReader().readFile("day-02/input.txt")
|
|
||||||
val res = Solution02().getSumOfCorrectGameIDs(text, CubeCount(12, 13, 14))
|
|
||||||
println(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun solvePart2() {
|
|
||||||
val text = ResourceReader().readFile("day-02/input.txt")
|
|
||||||
val res = Solution02().getSumOfPowers(text)
|
|
||||||
println(res)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue