/
Day05.kt
74 lines (63 loc) 路 2.59 KB
/
Day05.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
package y2023.day05
import AocPuzzle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
fun main() = Day05().runAll()
class Day05 : AocPuzzle<Long, Long>() {
override fun solve1(input: List<String>): Long {
val almanac = parseAlmanac(input)
return almanac.seeds.minOf { almanac.seedToLocation(it) }
}
override fun solve2(input: List<String>): Long {
val almanac = parseAlmanac(input)
return runBlocking(Dispatchers.Default) {
almanac.seeds
.chunked(2)
.map { (start, len) ->
async {
(start..<(start + len)).minOf { almanac.seedToLocation(it) }
.also { println(" Min of seeds $start [len: $len]: $it") }
}
}
.minOf { it.await() }
}
}
private fun parseAlmanac(input: List<String>): Almanac {
val seeds = input.first().substringAfter("seeds:").split(" ").filter { it.isNotBlank() }.map { it.trim().toLong() }
return Almanac(seeds).apply {
categories += parseRanges(input, "seed-to-soil")
categories += parseRanges(input, "soil-to-fertilizer")
categories += parseRanges(input, "fertilizer-to-water")
categories += parseRanges(input, "water-to-light")
categories += parseRanges(input, "light-to-temperature")
categories += parseRanges(input, "temperature-to-humidity")
categories += parseRanges(input, "humidity-to-location")
}
}
private fun parseRanges(input: List<String>, key: String): Category {
val ranges = input
.dropWhile { !it.startsWith(key) }.drop(1)
.takeWhile { it.isNotBlank() }
.map { line ->
val (dst, src, len) = line.split(" ").map { it.trim().toLong() }
RangeMap(src, dst, len)
}
return Category(key, ranges)
}
}
class Almanac(val seeds: List<Long>) {
val categories = mutableListOf<Category>()
fun seedToLocation(seed: Long): Long {
var translated = seed
for (cat in categories) {
translated = cat.ranges.firstOrNull { translated in it }?.map(translated) ?: translated
}
return translated
}
}
data class Category(val name: String, val ranges: List<RangeMap>)
data class RangeMap(val srcFrom: Long, val dstFrom: Long, val len: Long) {
operator fun contains(value: Long) = value in srcFrom ..< (srcFrom+len)
fun map(value: Long): Long = value - srcFrom + dstFrom
}