Day11.kt 2.86 KB
Newer Older
Kevin Turner's avatar
Kevin Turner committed
1 2 3 4
package net.keturn.advent2018

import kotlin.system.measureTimeMillis

Kevin Turner's avatar
Kevin Turner committed
5
const val GRID_SIZE = 300
Kevin Turner's avatar
Kevin Turner committed
6 7 8 9 10 11 12

fun serialNumber(): Int {
    return inputDirectory.resolve("11").readText().toInt()
}


private fun hundredsDigit(n: Int): Int {
Kevin Turner's avatar
Kevin Turner committed
13
    return (n%1000) / 100
Kevin Turner's avatar
Kevin Turner committed
14 15 16 17 18 19 20 21 22 23
}


fun powerAtPoint(serial: Int, x: Int, y: Int): Int {
    val rackID = x + 10
    val bloo = (rackID * y  + serial) * rackID
    return hundredsDigit(bloo) - 5
}


Kevin Turner's avatar
Kevin Turner committed
24 25
fun searchGrid3(serial: Int): Coordinate {
    val everyplace = (1..(GRID_SIZE - 2)).flatMap { x -> (1..(GRID_SIZE - 2)).map { y-> Coordinate(x, y)}}
Kevin Turner's avatar
Kevin Turner committed
26 27 28 29 30 31 32 33 34

    return everyplace.maxBy { (x, y) ->
        powerAtPoint(serial, x, y) + powerAtPoint(serial, x + 1, y) + powerAtPoint(serial, x + 2, y) +
        powerAtPoint(serial, x, y + 1) + powerAtPoint(serial, x + 1, y + 1) + powerAtPoint(serial, x + 2, y + 1) +
        powerAtPoint(serial, x, y + 2) + powerAtPoint(serial, x + 1, y + 2) + powerAtPoint(serial, x + 2, y + 2)
    }!!
}


Kevin Turner's avatar
Kevin Turner committed
35
fun powerInGrid(serial: Int, x: Int, y: Int, size: Int): Int {
36
    val everyplace = (x until (x+size)).flatMap { ix -> (y until (y + size)).map { iy-> Coordinate(ix, iy)}}.parallelStream()
Kevin Turner's avatar
Kevin Turner committed
37

38
    return everyplace.mapToInt { (ix, iy) -> powerAtPoint(serial, ix, iy)}.sum()
Kevin Turner's avatar
Kevin Turner committed
39 40 41 42 43 44
}


fun searchGridAny(serial: Int, size: Int): Pair<Int, Coordinate> {
    val everyplace = (1..(GRID_SIZE - size + 1)).flatMap { x -> (1..(GRID_SIZE - size + 1)).map { y-> Coordinate(x, y)}}

45 46 47 48 49 50
    val powerAtEveryplace = everyplace.parallelStream().map { coord -> powerInGrid(serial, coord.x, coord.y, size) to coord}

    val mostPower = powerAtEveryplace.max { a, b -> a.first.compareTo(b.first) }.get()

    println("grid size $size $mostPower")
    return mostPower
Kevin Turner's avatar
Kevin Turner committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
}


private fun <E, V: Comparable<V>> List<E>.maxValueBy(f: (E) -> V): Pair<V, E>? {
    if (isEmpty()) {
        return null
    }
    var maxSoFar: Comparable<V> = f(this[0])
    var inputOfMaxSoFar = this[0]
    for (i in this.listIterator(1)) {
        val current = f(i)
        if (maxSoFar < current) {
            maxSoFar = current
            inputOfMaxSoFar = i
        }
    }
    @Suppress("UNCHECKED_CAST")
    return (maxSoFar to inputOfMaxSoFar) as Pair<V, E>
}


fun searchAllSizes(serial: Int): Pair<Int, Coordinate> {
    val allSizes = (1 until GRID_SIZE).toList()

    val powerForSize =  allSizes.map { size -> searchGridAny(serial, size) }
    val mostPowerGrid = powerForSize.maxBy { (power, _) -> power }!!
    val mostPowerSize = powerForSize.indexOf(mostPowerGrid) + 1
    return mostPowerSize to mostPowerGrid.second
}


Kevin Turner's avatar
Kevin Turner committed
82 83 84 85 86
fun main(args: Array<String>) {
    val serial = serialNumber()

    lateinit var mostPowerAt: Coordinate
    val searchTime = measureTimeMillis {
Kevin Turner's avatar
Kevin Turner committed
87
        mostPowerAt = searchGrid3(serial)
Kevin Turner's avatar
Kevin Turner committed
88 89
    }
    println("Most power at $mostPowerAt [$searchTime ms]")
Kevin Turner's avatar
Kevin Turner committed
90 91 92 93 94
    println(powerAtPoint(serial, mostPowerAt.x, mostPowerAt.y))

    println("Part Two:")
    println(searchAllSizes(serial))
}