-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day20.kt
81 lines (69 loc) · 2.88 KB
/
Day20.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
68
69
70
71
72
73
74
75
76
77
78
79
80
package aoc2021.day20
import aoc2020.day05.binaryToDecimal
import util.Coord
import util.readInputLineByLine
fun readInputToImages(inputString: String): ImageEnhancementData {
var algorithm = ""
val map = mutableMapOf<Coord, Char>()
readInputLineByLine(inputString).forEachIndexed { index, line ->
if (index == 0) {
algorithm = line
} else if (line.isNotEmpty()) {
var x = 0
line.toCharArray().forEach { char ->
map[Coord(x, index - 2)] = char
x++
}
}
}
return ImageEnhancementData(algorithm, map)
}
fun enhanceAndCountPixels(inputData: ImageEnhancementData, times: Int = 2, realInput: Boolean): Int {
var result = applyImageEnhancementAlgorithm(inputData.algorithm, inputData.inputImage, 1, realInput)
(2..times).forEach { step ->
result = applyImageEnhancementAlgorithm(inputData.algorithm, result, step, realInput)
}
return result.values.count { it == '#' }
}
fun applyImageEnhancementAlgorithm(algorithm: String, inputImage: Map<Coord, Char>, step: Int, realInput: Boolean): Map<Coord, Char> {
val resultImage = mutableMapOf<Coord, Char>()
val expandedImage = expandInputImage(inputImage, step, realInput)
expandedImage.entries.forEach { entry ->
val algorithmIndex = convertToNumber(getSurroundingSquare(entry.key, expandedImage, realInput, step))
resultImage[entry.key] = algorithm[algorithmIndex]
}
return resultImage
}
private fun expandInputImage(inputImage: Map<Coord, Char>, step: Int, realInput: Boolean): Map<Coord, Char> {
val expandedImage = inputImage.toMutableMap()
val (minX, maxX) = Pair(inputImage.keys.minOf { it.x }, inputImage.keys.maxOf { it.x })
val (minY, maxY) = Pair(inputImage.keys.minOf { it.y }, inputImage.keys.maxOf { it.y })
for (y in minY - 1..maxY + 1)
for (x in minX - 1..maxX + 1)
if (expandedImage[Coord(x, y)] == null)
expandedImage[Coord(x, y)] = if (realInput && step % 2 == 0) '#' else '.'
return expandedImage
}
fun convertToNumber(inputString: String): Int {
val inputBinary = inputString.replace("#", "1").replace(".", "0")
return binaryToDecimal(inputBinary.toInt())
}
fun getSurroundingSquare(cell: Coord, inputImage: Map<Coord, Char>, realInput: Boolean, step: Int = 1): String {
val expandedImage = expandInputImage(inputImage, step, realInput)
return getNeighbors(cell).map { expandedImage[it] }.joinToString("")
}
fun getNeighbors(coord: Coord): List<Coord> {
val neighbors = mutableListOf<Coord>()
val (x, y) = Pair(coord.x, coord.y)
neighbors.add(Coord(x - 1, y - 1))
neighbors.add(Coord(x, y - 1))
neighbors.add(Coord(x + 1, y - 1))
neighbors.add(Coord(x - 1, y))
neighbors.add(Coord(x, y))
neighbors.add(Coord(x + 1, y))
neighbors.add(Coord(x - 1, y + 1))
neighbors.add(Coord(x, y + 1))
neighbors.add(Coord(x + 1, y + 1))
return neighbors
}
class ImageEnhancementData(val algorithm: String, val inputImage: Map<Coord, Char>)