-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDay11.kt
67 lines (53 loc) · 2.37 KB
/
Day11.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
* Copyright (c) 2018 by Todd Ginsberg
*/
/**
* Advent of Code 2018, Day 11 - Chronal Charge
*
* Problem Description: http://adventofcode.com/2018/day/11
* Blog Post/Commentary: https://todd.ginsberg.com/post/advent-of-code/2018/day11/
*/
package com.ginsberg.advent2018
class Day11(private val serialNumber: Int, private val gridSize: Int = 300) {
private val summedAreaTable: Array<IntArray> = createSummedAreaTable()
fun solvePart1(): Pair<Int, Int> =
bestSquareBetweenSizes(3, 3).run { Pair(x, y) }
fun solvePart2(): Triple<Int, Int, Int> =
bestSquareBetweenSizes(1, gridSize).run { Triple(x, y, n) }
private fun bestSquareBetweenSizes(smallest: Int, largest: Int): GridSquare =
(smallest..largest).asSequence().flatMap { n ->
(n until gridSize).asSequence().flatMap { y ->
(n until gridSize).asSequence().map { x ->
GridSquare(x - n + 1, y - n + 1, sumOfSquare(x, y, n), n)
}
}
}.maxBy { it.power }!!
private fun sumOfSquare(x: Int, y: Int, n: Int): Int {
val lowerRight = summedAreaTable[y][x]
val upperRight = if (y - n >= 0) summedAreaTable[y - n][x] else 0
val lowerLeft = if (x - n >= 0) summedAreaTable[y][x - n] else 0
val upperLeft = if (x - n >= 0 && y - n >= 0) summedAreaTable[y - n][x - n] else 0
return lowerRight + upperLeft - upperRight - lowerLeft
}
private fun createSummedAreaTable(): Array<IntArray> {
// Create an empty grid
val summedGrid: Array<IntArray> = Array(gridSize) { IntArray(gridSize) }
// Fill the grid
(0 until gridSize).forEach { y ->
(0 until gridSize).forEach { x ->
val me = powerLevel(x, y)
val up = if (y == 0) 0 else summedGrid[y - 1][x]
val left = if (x == 0) 0 else summedGrid[y][x - 1]
val upperLeft = if (x == 0 || y == 0) 0 else summedGrid[y - 1][x - 1]
summedGrid[y][x] = me + up + left - upperLeft
}
}
return summedGrid
}
private fun powerLevel(x: Int, y: Int): Int {
val rackId = x + 10
return (((rackId * y) + serialNumber) * rackId).hundreds() - 5
}
private fun Int.hundreds(): Int = (this / 100) % 10
private class GridSquare(val x: Int, val y: Int, val power: Int, val n: Int)
}