generated from kotlin-hands-on/advent-of-code-kotlin-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
802f5d9
commit ddec081
Showing
5 changed files
with
236 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package day05 | ||
|
||
import fetchInput | ||
import kotlinx.coroutines.async | ||
import kotlinx.coroutines.awaitAll | ||
import kotlinx.coroutines.runBlocking | ||
import println | ||
|
||
fun main() { | ||
val input = fetchInput(5) | ||
part1(input).println() | ||
part2(input).println() | ||
} | ||
|
||
fun part1(input: List<String>): Long { | ||
val parsed = parseDay5(input) | ||
return parsed.seeds.minOf { | ||
seedToLocation(it, parsed, input) | ||
} | ||
} | ||
|
||
fun part2(input: List<String>): Long = | ||
runBlocking { | ||
val parsed = parseDay5(input) | ||
val newSeeds = | ||
parsed.seeds | ||
.chunked(2) | ||
.map { (seed, range) -> | ||
seed until seed + range | ||
} | ||
|
||
val locations = mutableSetOf<Long>() | ||
|
||
newSeeds.map { longRange -> | ||
async { | ||
var min: Long = Long.MAX_VALUE | ||
for (seed in longRange) { | ||
min = minOf(seedToLocation(seed, parsed, input), min) | ||
} | ||
min | ||
} | ||
}.awaitAll().forEach { | ||
locations.add(it) | ||
} | ||
locations.min() | ||
} | ||
|
||
data class Day05Game( | ||
val seeds: List<Long>, | ||
val sToSMap: String, | ||
val sToFMap: String, | ||
val fToWMap: String, | ||
val wToLMap: String, | ||
val lToTMap: String, | ||
val tToHMap: String, | ||
val hToLMap: String, | ||
) | ||
|
||
fun parseDay5(input: List<String>): Day05Game { | ||
// a regex is probably way simpler. | ||
val seeds = | ||
input | ||
.first() | ||
.split(": ") | ||
.drop(1) | ||
.first() | ||
.split(" ") | ||
.map(String::toLong) | ||
|
||
return Day05Game( | ||
seeds = seeds, | ||
sToSMap = "seed-to-soil map:", | ||
sToFMap = "soil-to-fertilizer map:", | ||
fToWMap = "fertilizer-to-water map:", | ||
wToLMap = "water-to-light map:", | ||
lToTMap = "light-to-temperature map:", | ||
tToHMap = "temperature-to-humidity map:", | ||
hToLMap = "humidity-to-location map:", | ||
) | ||
} | ||
|
||
private fun convertToDestination( | ||
seed: Long, | ||
mapName: String, | ||
input: List<String>, | ||
): Long { | ||
val startIndex = input.indexOf(mapName) + 1 | ||
|
||
for (i in startIndex until input.size) { | ||
val line = input[i] | ||
if (line.isBlank()) break | ||
|
||
val parsed = line.split(" ").map(String::toLong) | ||
|
||
val (destination, source, range) = parsed | ||
if (seed in source until source + range) { | ||
val offset = destination - source | ||
return seed + offset | ||
} | ||
} | ||
return seed | ||
} | ||
|
||
fun seedToLocation( | ||
seed: Long, | ||
game: Day05Game, | ||
input: List<String>, | ||
): Long { | ||
var key = seed | ||
val transformations = | ||
listOf(game.sToSMap, game.sToFMap, game.fToWMap, game.wToLMap, game.lToTMap, game.tToHMap, game.hToLMap) | ||
for (transform in transformations) { | ||
val value = convertToDestination(key, transform, input) | ||
key = value | ||
} | ||
return key | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package day05 | ||
|
||
import org.junit.jupiter.api.Assertions.assertEquals | ||
import org.junit.jupiter.api.Test | ||
|
||
class Day05Test { | ||
@Test | ||
fun seedReturnsCorrectSoil() { | ||
val expected = listOf(82L, 43L, 86L, 35L) | ||
val parsed = parseDay5(sampleInput) | ||
val seeds = parsed.seeds | ||
val actual = seeds.map { seedToLocation(it, parsed, sampleInput) } | ||
assertEquals(expected, actual) | ||
} | ||
|
||
@Test | ||
fun part2ReturnsLowestLocation() { | ||
val expected = 46L | ||
val parsed = parseDay5(sampleInput) | ||
val newseeds = | ||
parsed.seeds.chunked(2).map { | ||
it[0] until it[0] + it[1] | ||
} | ||
val locations = mutableSetOf<Long>() | ||
|
||
newseeds.forEach { longRange -> | ||
var min: Long = Long.MAX_VALUE | ||
for (seed in longRange) { | ||
min = minOf(seedToLocation(seed, parsed, sampleInput), min) | ||
locations.add(min) | ||
} | ||
} | ||
val actual = locations.min() | ||
assertEquals(expected, actual) | ||
} | ||
|
||
private val sampleInput = | ||
""" | ||
seeds: 79 14 55 13 | ||
seed-to-soil map: | ||
50 98 2 | ||
52 50 48 | ||
soil-to-fertilizer map: | ||
0 15 37 | ||
37 52 2 | ||
39 0 15 | ||
fertilizer-to-water map: | ||
49 53 8 | ||
0 11 42 | ||
42 0 7 | ||
57 7 4 | ||
water-to-light map: | ||
88 18 7 | ||
18 25 70 | ||
light-to-temperature map: | ||
45 77 23 | ||
81 45 19 | ||
68 64 13 | ||
temperature-to-humidity map: | ||
0 69 1 | ||
1 0 69 | ||
humidity-to-location map: | ||
60 56 37 | ||
56 93 4 | ||
""".trimIndent().split("\n") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package day06 | ||
|
||
import org.junit.jupiter.api.Assertions.assertEquals | ||
import org.junit.jupiter.api.Test | ||
|
||
class Day06KtTest { | ||
@Test | ||
fun parseRacesReturnsCorrectResult() { | ||
val expected = listOf(Pair(7, 9), Pair(15, 40), Pair(30, 200)) | ||
val actual = parseDay6(sampleInput) | ||
assertEquals(expected, actual) | ||
} | ||
|
||
@Test | ||
fun parseRacesReturnsCorrectResultP2() { | ||
val expected = Pair(71530L, 940200L) | ||
val actual = parseDay6P2(sampleInput) | ||
assertEquals(expected, actual) | ||
} | ||
|
||
@Test | ||
fun findBestSpeedReturnsCorrectResult() { | ||
val expected = listOf<Long>(2, 3, 4, 5) | ||
val actual = findBestSpeeds(parseDay6(sampleInput).first()) | ||
assertEquals(expected, actual) | ||
} | ||
|
||
@Test | ||
fun part2ReturnsCorrectResult() { | ||
val expected = 71503 | ||
val actual = part2(sampleInput) | ||
assertEquals(expected, actual) | ||
} | ||
|
||
private val sampleInput = | ||
""" | ||
Time: 7 15 30 | ||
Distance: 9 40 200 | ||
""".trimIndent().split("\n") | ||
} |