Update solution

This commit is contained in:
Ivan R. 2024-01-26 17:42:55 +05:00
parent b636dd4c43
commit 36dc294e98
Signed by: lumin
GPG key ID: 927D3132247BDE4E
2 changed files with 59 additions and 40 deletions

View file

@ -1,6 +1,6 @@
class Solution05(lines: List<String>) { class Solution05(lines: List<String>) {
private var seeds: MutableList<ULong> = mutableListOf() private var seeds: MutableList<ULong> = mutableListOf()
private var maps: MutableMap<String, Ranges> = mutableMapOf() private var maps: MutableList<MapList> = mutableListOf()
init { init {
// Parse seeds // Parse seeds
@ -8,24 +8,16 @@ class Solution05(lines: List<String>) {
seeds.addAll(seedsStr.split(" ").map{it.toULong()}) seeds.addAll(seedsStr.split(" ").map{it.toULong()})
// Parse all maps // Parse all maps
var currentSrc = ""
for (line in lines.subList(2, lines.size)) { for (line in lines.subList(2, lines.size)) {
if (line.isEmpty()) continue if (line.isEmpty()) continue
if (line.contains(" map:")) { if (line.contains(" map:")) {
val (mapTitle, _) = line.split(" ") maps.add(MapList())
val (src, dest) = mapTitle.split("-to-")
currentSrc = src
if (!maps.containsKey(currentSrc)) {
maps[currentSrc] = Ranges(dest)
}
continue continue
} }
val (destRangeStart, srcRangeStart, rangeLength) = line.split(" ") val (destRangeStart, srcRangeStart, rangeLength) = line.split(" ")
maps[currentSrc]?.addRange( maps.last().addRange(
srcRangeStart.toULong(), srcRangeStart.toULong(),
destRangeStart.toULong(), destRangeStart.toULong(),
rangeLength.toULong(), rangeLength.toULong(),
@ -33,52 +25,63 @@ class Solution05(lines: List<String>) {
} }
} }
// Part 1.
fun getLowestLocationNumber(): ULong { fun getLowestLocationNumber(): ULong {
return seeds return seeds
.map{convertSeedNumber(it, "location")} .map{
var num = it
for (map in maps) {
num = map.mapSrcNumberToDest(num)
}
num
}
.min() .min()
} }
// Part 2.
fun getLowestLocationNumberForRangeOfSeeds(): ULong { fun getLowestLocationNumberForRangeOfSeeds(): ULong {
val allSeeds: MutableSet<ULong> = mutableSetOf() // Available location numbers.
var currentRanges = maps
.last()
.mappers
.map{RangeFromLoc(it.destRangeStart, it.rangeLength, it.destRangeStart)}
for (map in maps.reversed()) {
val newList: MutableList<RangeFromLoc> = mutableListOf()
for (mapper in map.mappers) {
// Find intersections
currentRanges
for (rng in currentRanges) {
for (i in 0..<seeds.size step 2) {
for (j in seeds[i]..<seeds[i]+seeds[i+1]) {
allSeeds.add(j)
} }
} }
return allSeeds currentRanges = newList
.map{convertSeedNumber(it, "location")}
.min()
} }
private fun convertSeedNumber(seed: ULong, target: String): ULong { return 0UL
var dest = "seed"
var num = seed
while (dest != target) {
val ranges = maps[dest]!!
dest = ranges.destName
num = ranges.mapNumber(num)
}
return num
} }
} }
data class Ranges(val destName: String) { // Map stores the rules for matching one number to another.
val ranges: MutableList<Range> = mutableListOf() class MapList() {
val mappers: MutableList<Mapper> = mutableListOf()
fun addRange(sourceRangeStart: ULong, destRangeStart: ULong, rangeLength: ULong) { fun addRange(sourceRangeStart: ULong, destRangeStart: ULong, rangeLength: ULong) {
ranges.add(Range(sourceRangeStart, destRangeStart, rangeLength)) mappers.add(
Mapper(sourceRangeStart, destRangeStart, rangeLength),
)
} }
fun mapNumber(src: ULong): ULong { fun mapSrcNumberToDest(src: ULong): ULong {
for (range in ranges) { for (range in mappers) {
if (src >= range.sourceRangeStart && src < range.sourceRangeStart + range.rangeLength) { if (range.isNumberInSrcRange(src)) {
return range.destRangeStart + src - range.sourceRangeStart return range.srcValueToDest(src)
} }
} }
@ -86,4 +89,20 @@ data class Ranges(val destName: String) {
} }
} }
data class Range(val sourceRangeStart: ULong, val destRangeStart: ULong, val rangeLength: ULong) // Mapper contains one line of map.
data class Mapper(val sourceRangeStart: ULong, val destRangeStart: ULong, val rangeLength: ULong) {
fun srcValueToDest(v: ULong): ULong {
return destRangeStart + v - sourceRangeStart
}
fun isNumberInSrcRange(num: ULong): Boolean {
return num >= sourceRangeStart && num < sourceRangeStart + rangeLength
}
}
// Range of numbers with the first number of corresponding location.
data class RangeFromLoc(val rangeStart: ULong, val rangeLength: ULong, val locationStart: ULong) {
fun getIntersection(newRangeStart: ULong, newRangeLength: ULong): RangeFromLoc {
return RangeFromLoc(rangeStart, rangeLength, locationStart)
}
}

View file

@ -13,7 +13,7 @@ class Solution05Test {
fun solvePart1() { fun solvePart1() {
val text = ResourceReader().readFile("day-05/input.txt") val text = ResourceReader().readFile("day-05/input.txt")
val res = Solution05(text).getLowestLocationNumber() val res = Solution05(text).getLowestLocationNumber()
println(res) assertEquals(621354867UL, res)
} }
@Test @Test