-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day18.kt
94 lines (71 loc) · 2.72 KB
/
Day18.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package tr.emreone.adventofcode.days
import tr.emreone.kotlin_utils.Logger.logger
import tr.emreone.kotlin_utils.math.Point3D
import java.util.*
import kotlin.math.min
import kotlin.math.max
object Day18 {
data class Cube(val center: Point3D) {
fun possibleDirectNeighbors(): List<Cube> {
return listOf(
Cube(Point3D(center.x - 1, center.y, center.z)),
Cube(Point3D(center.x + 1, center.y, center.z)),
Cube(Point3D(center.x, center.y - 1, center.z)),
Cube(Point3D(center.x, center.y + 1, center.z)),
Cube(Point3D(center.x, center.y, center.z - 1)),
Cube(Point3D(center.x, center.y, center.z + 1))
)
}
}
class Droplet(input: List<String>) {
val cubes = input.map { line ->
val (x, y, z) = line.split(",").map { it.toLong() }
Cube(Point3D(x, y, z))
}
private val outCubes = mutableSetOf<Cube>()
private val inCubes = mutableSetOf<Cube>()
fun calcSurfaceArea(): Int {
return this.cubes.sumOf { cube ->
val neighbors = cube.possibleDirectNeighbors()
6 - neighbors.count { this.cubes.contains(it) }
}
}
fun calcOnlyOutsideSurfaceArea(): Int {
outCubes.clear()
inCubes.clear()
fun reachesOutside(cube: Cube): Boolean {
if (outCubes.contains(cube)) return true
if (inCubes.contains(cube)) return false
val seenCubes = mutableSetOf<Cube>()
val queue = mutableListOf<Cube>(cube)
while(queue.isNotEmpty()) {
val c = queue.removeFirst()
if (this.cubes.contains(c))
continue
if (seenCubes.contains(c))
continue
seenCubes.add(c)
if (seenCubes.size > this.cubes.size) {
seenCubes.forEach { outCubes.add(it) }
return true
}
queue.addAll(c.possibleDirectNeighbors())
}
seenCubes.forEach { inCubes.add(it) }
return false
}
return this.cubes.sumOf { cube ->
val neighbors = cube.possibleDirectNeighbors()
neighbors.count { reachesOutside(it) }
}
}
}
fun part1(input: List<String>): Int {
val droplet = Droplet(input)
return droplet.calcSurfaceArea()
}
fun part2(input: List<String>): Int {
val droplet = Droplet(input)
return droplet.calcOnlyOutsideSurfaceArea()
}
}