day5: Fix integer overflow bug
This commit is contained in:
parent
713bc2b47d
commit
13454b3f18
62
day5/day5.kt
62
day5/day5.kt
|
@ -1,6 +1,6 @@
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
typealias Map = Pair<UIntRange, UIntRange>
|
typealias Map = Pair<LongRange, LongRange>
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val input = File("input")
|
val input = File("input")
|
||||||
|
@ -13,11 +13,11 @@ fun main() {
|
||||||
println(part2(seedRanges, maps))
|
println(part2(seedRanges, maps))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun part1(seeds: List<UInt>, maps: List<List<Map>>): UInt {
|
fun part1(seeds: List<Long>, maps: List<List<Map>>): Long {
|
||||||
return seeds.map { seed -> maps.fold(seed) { toFind, map -> findMapping(toFind, map) } }.min()
|
return seeds.map { seed -> maps.fold(seed) { toFind, map -> findMapping(toFind, map) } }.min()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findMapping(toFind: UInt, maps: List<Map>): UInt {
|
fun findMapping(toFind: Long, maps: List<Map>): Long {
|
||||||
for (map in maps) {
|
for (map in maps) {
|
||||||
if (toFind >= map.first.first && toFind <= map.first.last) {
|
if (toFind >= map.first.first && toFind <= map.first.last) {
|
||||||
val index = toFind - map.first.first
|
val index = toFind - map.first.first
|
||||||
|
@ -34,50 +34,24 @@ fun findMapping(toFind: UInt, maps: List<Map>): UInt {
|
||||||
return toFind
|
return toFind
|
||||||
}
|
}
|
||||||
|
|
||||||
fun part2(seedRanges: List<UIntRange>, maps: List<List<Map>>): UInt {
|
fun part2(seedRanges: List<LongRange>, maps: List<List<Map>>): Long {
|
||||||
return seedRanges
|
return seedRanges
|
||||||
.map { range ->
|
.map { range ->
|
||||||
maps
|
maps
|
||||||
.fold(listOf(range)) { toReduce, map -> findReduction(toReduce, map) }
|
.fold(listOf(range)) { toReduce, map -> findReduction(toReduce, map) }
|
||||||
.filter {
|
|
||||||
// TODO(tlater): Remove this cursed filter
|
|
||||||
//
|
|
||||||
// Sometimes the source and range match up
|
|
||||||
// perfectly, and the destination starts
|
|
||||||
// with 0.
|
|
||||||
//
|
|
||||||
// Maybe this is a bug in the puzzle (?!),
|
|
||||||
// or whenever this happens my logic
|
|
||||||
// breaks down and the resulting
|
|
||||||
// translated range always ends up in the
|
|
||||||
// result.
|
|
||||||
//
|
|
||||||
// Nonetheless, filtering these 0s out
|
|
||||||
// gives the right answer.
|
|
||||||
//
|
|
||||||
// More likely it's a booby trap for
|
|
||||||
// *exactly* the logical fallacy I'm
|
|
||||||
// committing?
|
|
||||||
//
|
|
||||||
// That, *or* it's just unlikely any one
|
|
||||||
// range is the lowest in the end, and
|
|
||||||
// these don't happen to contribute, while
|
|
||||||
// the rest is computed correctly.
|
|
||||||
it.first != 0u
|
|
||||||
}
|
|
||||||
.map { it.first }
|
.map { it.first }
|
||||||
.min()
|
.min()
|
||||||
}
|
}
|
||||||
.min()
|
.min()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findReduction(toReduce: List<UIntRange>, maps: List<Map>): List<UIntRange> {
|
fun findReduction(toReduce: List<LongRange>, maps: List<Map>): List<LongRange> {
|
||||||
var result: MutableList<UIntRange> = mutableListOf()
|
var result: MutableList<LongRange> = mutableListOf()
|
||||||
var reducing: MutableList<UIntRange> = mutableListOf()
|
var reducing: MutableList<LongRange> = mutableListOf()
|
||||||
reducing.addAll(toReduce)
|
reducing.addAll(toReduce)
|
||||||
|
|
||||||
for (map in maps) {
|
for (map in maps) {
|
||||||
var next: MutableList<UIntRange> = mutableListOf()
|
var next: MutableList<LongRange> = mutableListOf()
|
||||||
val source = map.first
|
val source = map.first
|
||||||
val destination = map.second
|
val destination = map.second
|
||||||
|
|
||||||
|
@ -96,17 +70,17 @@ fun findReduction(toReduce: List<UIntRange>, maps: List<Map>): List<UIntRange> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDestinationForOverlap(
|
fun getDestinationForOverlap(
|
||||||
overlap: UIntRange,
|
overlap: LongRange,
|
||||||
source: UIntRange,
|
source: LongRange,
|
||||||
destination: UIntRange
|
destination: LongRange
|
||||||
): UIntRange {
|
): LongRange {
|
||||||
val startDiff = overlap.first - source.first
|
val startDiff = overlap.first - source.first
|
||||||
val endDiff = source.last - overlap.last
|
val endDiff = source.last - overlap.last
|
||||||
|
|
||||||
return destination.first + startDiff..destination.last - endDiff
|
return destination.first + startDiff..destination.last - endDiff
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOverlap(range1: UIntRange, range2: UIntRange): Pair<UIntRange?, List<UIntRange>> {
|
fun getOverlap(range1: LongRange, range2: LongRange): Pair<LongRange?, List<LongRange>> {
|
||||||
val start =
|
val start =
|
||||||
when {
|
when {
|
||||||
range1.first <= range2.first -> range2.first
|
range1.first <= range2.first -> range2.first
|
||||||
|
@ -124,24 +98,24 @@ fun getOverlap(range1: UIntRange, range2: UIntRange): Pair<UIntRange?, List<UInt
|
||||||
if (start > end) {
|
if (start > end) {
|
||||||
return Pair(null, listOf(range1))
|
return Pair(null, listOf(range1))
|
||||||
} else {
|
} else {
|
||||||
val excess: MutableList<UIntRange> = mutableListOf()
|
val excess: MutableList<LongRange> = mutableListOf()
|
||||||
|
|
||||||
if (start > range1.first) {
|
if (start > range1.first) {
|
||||||
excess.add(range1.first ..< start)
|
excess.add(range1.first ..< start)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (range1.last > end) {
|
if (range1.last > end) {
|
||||||
excess.add(end + 1u..range1.last)
|
excess.add(end + 1L..range1.last)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Pair(start..end, excess)
|
return Pair(start..end, excess)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseInput(input: File): Pair<List<UInt>, List<List<Map>>> {
|
fun parseInput(input: File): Pair<List<Long>, List<List<Map>>> {
|
||||||
val text = input.bufferedReader()
|
val text = input.bufferedReader()
|
||||||
|
|
||||||
val seeds = text.readLine().split(": ")[1].split(" ").map { it.toUInt() }
|
val seeds = text.readLine().split(": ")[1].split(" ").map { it.toLong() }
|
||||||
text.readLine()
|
text.readLine()
|
||||||
|
|
||||||
var line = text.readLine()
|
var line = text.readLine()
|
||||||
|
@ -152,7 +126,7 @@ fun parseInput(input: File): Pair<List<UInt>, List<List<Map>>> {
|
||||||
line == "" -> Unit // Skip empty lines
|
line == "" -> Unit // Skip empty lines
|
||||||
line.endsWith(':') -> maps.add(mutableListOf())
|
line.endsWith(':') -> maps.add(mutableListOf())
|
||||||
else -> {
|
else -> {
|
||||||
val (destination, source, length) = line.split(" ").map { it.toUInt() }
|
val (destination, source, length) = line.split(" ").map { it.toLong() }
|
||||||
maps.last()
|
maps.last()
|
||||||
.add(Pair(source ..< source + length, destination ..< destination + length))
|
.add(Pair(source ..< source + length, destination ..< destination + length))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue