1+ import java.nio.file.Path
2+ import kotlin.io.path.readLines
3+ import kotlin.math.max
4+ import kotlin.math.min
5+
6+
7+ class Day05 : Day {
8+ override fun partOne (filename : String , verbose : Boolean ): Int {
9+ val (freshRanges, ingredients) = filename.asPath().parseInventory()
10+
11+ return ingredients.count { ingredient ->
12+ freshRanges.any { ingredient in it }
13+ }
14+ }
15+
16+ override fun partTwo (filename : String , verbose : Boolean ): Long {
17+ val (freshRanges, _) = filename.asPath().parseInventory()
18+ val sortedRanges = freshRanges.sortedBy { it.last }
19+ val merged = mergeOverlap(sortedRanges)
20+ return merged.sumOf { it.last - it.first + 1 }
21+ }
22+
23+ private fun Path.parseInventory (): Pair <List <LongRange >, List<Long>> {
24+ var freshRangesDone = false
25+
26+ val freshRanges = mutableListOf<LongRange >()
27+ val ingredients = mutableListOf<Long >()
28+ readLines().forEach { line ->
29+ when {
30+ line.isBlank() -> freshRangesDone = true
31+ freshRangesDone -> ingredients + = line.toLong()
32+ else -> {
33+ val (start, stop) = line.split(" -" )
34+ freshRanges + = start.toLong().. stop.toLong()
35+ }
36+ }
37+ }
38+ return freshRanges to ingredients
39+ }
40+
41+ private fun mergeOverlap (ranges : List <LongRange >): List <LongRange > {
42+ val merged = mutableListOf<LongRange >()
43+ var current = ranges.first()
44+ for (i in 1 .. < ranges.size) {
45+ val range = ranges[i]
46+ if (current.first <= range.last && range.first <= current.last) {
47+ current = min(current.first, range.first).. max(current.last, range.last)
48+ } else {
49+ merged + = current
50+ current = range
51+ }
52+ }
53+ merged + = current
54+ return merged
55+ }
56+
57+ companion object : Day .Main (" Day05.txt" ) {
58+ @JvmStatic
59+ fun main (args : Array <String >) = main()
60+ }
61+ }
0 commit comments