628 tokens in Kotlin for part 2 by Valentin Slawicek
Download solution
dataclassMapEntry(
valsource:String,
valdestination:String,
valsourceStart:Long,
valdestinationStart:Long,
valrangeLength:Long
){
valsourceRange=LongRange(sourceStart,sourceStart+rangeLength-1)
}
funmain(){
valmapEntries=mutableListOf<MapEntry>()
varseeds:List<LongRange>=emptyList()
varcurrentMap=""to""
generateSequence(::readLine)
.forEach{line->
when{
line.startsWith("seeds: ")->{
seeds=line.substringAfter("seeds: ")
.split(" ")
.map{it.toLong()}
.chunked(2)
.map{LongRange(it[0],it[0]+it[1]-1)}
}
line.endsWith(" map:")->{
currentMap=line.substringBefore("-")toline.substringAfter("-to-").substringBefore(" ")
}
line.isEmpty()->Unit
else->{
valmapEntryString=line.split(" ").map{it.toLong()}
mapEntries+=MapEntry(
source=currentMap.first,
destination=currentMap.second,
destinationStart=mapEntryString[0],
sourceStart=mapEntryString[1],
rangeLength=mapEntryString[2]
)
}
}
}
funLongRange.intersect(other:LongRange):LongRange{
returnLongRange(maxOf(this.first,other.first),minOf(this.last,other.last))
}
fungetMapEntries(source:String,range:LongRange):Map<MapEntry,LongRange>{
valrelevantMapEntries=mapEntries.filter{it.source==source}.sortedBy{it.sourceStart}
valtargetMapEntries=relevantMapEntries.toMutableList()
varlastEnd=-1L
relevantMapEntries.forEach{mapEntry->
if(mapEntry.sourceStart!=lastEnd+1){
targetMapEntries+=relevantMapEntries.first().copy(
sourceStart=lastEnd+1,
destinationStart=lastEnd+1,
rangeLength=mapEntry.sourceStart-lastEnd
)
}
lastEnd=mapEntry.sourceRange.last
}
targetMapEntries+=relevantMapEntries.first()
.copy(sourceStart=lastEnd+1,destinationStart=lastEnd+1,rangeLength=Long.MAX_VALUE-lastEnd)
returntargetMapEntries.filter{!it.sourceRange.intersect(range).isEmpty()}
.associateWith{mapEntry->
valoffset=mapEntry.destinationStart-mapEntry.sourceStart
valsourceIntersectedRange=mapEntry.sourceRange.intersect(range)
LongRange(sourceIntersectedRange.first+offset,sourceIntersectedRange.last+offset)
}
}
funresolve(source:String,range:LongRange):List<LongRange>{
valresolvedMapEntries=getMapEntries(source,range)
returnresolvedMapEntries.flatMap{(mapEntry,range)->
if(resolvedMapEntries.keys.first().destination=="location"){
listOf(range)
}else{
resolve(mapEntry.destination,range)
}
}
}
println(seeds.minOf{seed->resolve("seed",seed).minBy{it.first}.first})
}