AOC: solve 5th task

This commit is contained in:
Ivan R. 2024-02-05 00:27:57 +05:00
parent 4acdaa1deb
commit ecaf90adb4
No known key found for this signature in database
GPG key ID: 56C7BAAE859B302C
2 changed files with 75 additions and 90 deletions

View file

@ -45,103 +45,91 @@ class Solution05(lines: List<String>) {
// Part 2. // Part 2.
fun getLowestLocationNumberForRangeOfSeeds(): Long { fun getLowestLocationNumberForRangeOfSeeds(): Long {
var ranges = mutableListOf<RangeWithFirstSeed>() var ranges = mutableListOf<LongRange>()
for (i in seeds.indices step 2) { for (i in seeds.indices step 2) {
ranges.add( ranges.add(LongRange(seeds[i], seeds[i] + seeds[i+1] - 1))
RangeWithFirstSeed(
LongRange(seeds[i], seeds[i] + seeds[i+1] - 1),
seeds[i],
)
)
} }
for (map in maps) { for (map in maps) {
val newList = mutableListOf<RangeWithFirstSeed>() var minCheckedValue = Long.MIN_VALUE
val newList = mutableListOf<LongRange>()
for (mapper in map.mappers) { for (mapper in map.mappers.sortedBy{it.sourceRangeStart}) {
for (rng in ranges) { //
val maxStart = max(mapper.sourceRangeStart, rng.range.first) val mapperEnd = mapper.sourceRangeStart + mapper.rangeLength - 1
val minEndExcl = min(mapper.sourceRangeStart + mapper.rangeLength, rng.range.last + 1) val diff = mapper.destRangeStart - mapper.sourceRangeStart
val len = minEndExcl - maxStart // find all values before this range.
if (len > 0L) { val unmatchedValues = ranges
.filter{it.first < mapper.sourceRangeStart}
.map{LongRange(max(minCheckedValue, it.first), min(mapper.sourceRangeStart - 1, it.last))}
.filter{it.first <= it.last}
newList.addAll(unmatchedValues)
val destStart = mapper.destRangeStart + (maxStart - mapper.sourceRangeStart) // map values
newList.add( val overlappingLeftValues = ranges
RangeWithFirstSeed( .filter{it.first < mapper.sourceRangeStart && it.last >= mapper.sourceRangeStart && it.last <= mapperEnd}
LongRange(destStart, destStart + len - 1), .map{
rng.firstSeedInRange LongRange(
) max(mapper.sourceRangeStart, it.first) + diff,
it.last + diff,
) )
} }
} .filter{it.first <= it.last}
newList.addAll(overlappingLeftValues)
val overlappingMiddleValues = ranges
.filter{it.first >= mapper.sourceRangeStart && it.last <= mapperEnd}
.map{
LongRange(
it.first + diff, it.last + diff
)
}
.filter{it.first <= it.last}
newList.addAll(overlappingMiddleValues)
val overlappingRightValues = ranges
.filter{it.first >= mapper.sourceRangeStart && it.first <= mapperEnd && it.last >= mapperEnd}
.map{
LongRange(
it.first + diff,
min(it.last, mapperEnd) + diff
)
}
.filter{it.first <= it.last}
newList.addAll(overlappingRightValues)
val bigRanges = ranges
.filter{it.first < mapper.sourceRangeStart && it.last > mapperEnd}
.map{
LongRange(
mapper.sourceRangeStart + diff, mapperEnd + diff
)
}
.filter{it.first <= it.last}
newList.addAll(bigRanges)
minCheckedValue = mapperEnd + 1
} }
// понять, какие диапазоны значений остались неиспользованными, newList.addAll(
// тоже добавить их в список. ranges
.filter{it.last >= minCheckedValue}
val mprs = ListOfRanges(map.mappers.map{LongRange(it.sourceRangeStart, it.sourceRangeStart + it.rangeLength - 1)}.toMutableList()) .map{
LongRange(
for (rng in ranges) { max(it.first, minCheckedValue),
var currentRange = rng.range it.last,
var intrs = mprs
.findIntersectingRanges(rng.range)
.sortedBy{it.first}
if (intrs.isEmpty()) {
newList.add(
rng
)
continue
}
for (i in intrs.indices) {
if (intrs[i].start > currentRange.start) {
newList.add(
RangeWithFirstSeed(
LongRange(intrs[i].start, currentRange.start - 1),
rng.firstSeedInRange
)
) )
} }
)
var end = intrs[i].last
if (i < intrs.size - 1 && intrs[i].last < intrs[i+1].first - 1) {
end = intrs[i+1].first - 1
newList.add(
RangeWithFirstSeed(
LongRange(intrs[i].last + 1, intrs[i+1].first - 1),
rng.firstSeedInRange,
)
)
}
currentRange = LongRange(end + 1, currentRange.endInclusive)
}
if (!currentRange.isEmpty()) {
newList.add(
RangeWithFirstSeed(
currentRange,
rng.firstSeedInRange
)
)
}
}
ranges = newList ranges = newList
.map{
if (it.range.last >= it.range.first) it else RangeWithFirstSeed(LongRange(it.range.last, it.range.first), it.firstSeedInRange)
}
.toMutableList()
} }
return ranges return ranges
.map{it.range.first} .map{it.first}
.min() .min()
} }
} }
@ -177,13 +165,3 @@ data class Mapper(val sourceRangeStart: Long, val destRangeStart: Long, val rang
return num >= sourceRangeStart && num < sourceRangeStart + rangeLength return num >= sourceRangeStart && num < sourceRangeStart + rangeLength
} }
} }
data class RangeWithFirstSeed(val range: LongRange, val firstSeedInRange: Long) {
}
data class ListOfRanges(val ranges: MutableList<LongRange>) {
fun findIntersectingRanges(other: LongRange): List<LongRange> {
return ranges
.filter{it.last >= other.first && it.first <= other.last}
}
}

View file

@ -20,13 +20,20 @@ class Solution05Test {
fun testGetLowestLocationForRangeOfSeeds() { fun testGetLowestLocationForRangeOfSeeds() {
val text = ResourceReader().readFile("day-05/test.txt") val text = ResourceReader().readFile("day-05/test.txt")
val res = Solution05(text).getLowestLocationNumberForRangeOfSeeds() val res = Solution05(text).getLowestLocationNumberForRangeOfSeeds()
assertEquals(46L, res) assertEquals(46, res)
} }
@Test @Test
fun solvePart2() { fun solvePart2() {
val text = ResourceReader().readFile("day-05/input.txt") val text = ResourceReader().readFile("day-05/input.txt")
val res = Solution05(text).getLowestLocationNumberForRangeOfSeeds() val res = Solution05(text).getLowestLocationNumberForRangeOfSeeds()
println(res) println("Your answer: $res")
}
@Test
fun testPart2() {
val text = ResourceReader().readFile("day-05/input.txt")
val res = Solution05(text).getLowestLocationNumberForRangeOfSeeds()
assertEquals(15880236, res)
} }
} }