-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay7.kt
67 lines (58 loc) · 2.1 KB
/
Day7.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
package aoc2017.day07
import util.readInputLineByLine
import kotlin.math.absoluteValue
fun readInputAndFindRoot(path: String): String {
val leftSet = mutableSetOf<String>()
val rightSet = mutableSetOf<String>()
for (line in readInputLineByLine(path)) {
val split = line.split(" -> ")
val left = split[0].replace(Regex("\\(\\d+\\)"), "")
leftSet += left.trim()
if (split.size > 1) {
rightSet.addAll(split[1].split(", "))
}
}
return leftSet.subtract(rightSet).first()
}
fun readInputAndParseToTree(path: String): Int {
val nodesByName = mutableMapOf<String, Node>()
val parentChildPairs = mutableSetOf<Pair<Node, String>>()
val rowRegex = """\w+""".toRegex()
readInputLineByLine(path).forEach { it ->
val groups = rowRegex.findAll(it).toList().map { it.value }
val node = Node(groups[0], groups[1].toInt())
nodesByName[node.nodeId] = node
groups.drop(2).forEach {
parentChildPairs.add(Pair(node, it))
}
}
parentChildPairs.forEach { (parent, childName) ->
with(nodesByName.getValue(childName)) {
parent.children.add(this)
this.parent = parent
}
}
return nodesByName.values.firstOrNull { it.parent == null }!!.findImbalance()
}
data class Node(
val nodeId: String,
private val weight: Int,
var parent: Node? = null,
val children: MutableList<Node> = mutableListOf()
) {
fun findImbalance(imbalance: Int? = null): Int {
return if (imbalance != null && areChildrenBalanced) {
weight - imbalance
} else {
val subtrees = children.groupBy { it.totalWeight }
val imbalancedTree = subtrees.minByOrNull { it.value.size }!!.value.first()
imbalancedTree.findImbalance(imbalance ?: subtrees.keys.reduce { a, b -> a - b }.absoluteValue)
}
}
private val totalWeight: Int by lazy {
weight + children.sumBy { it.totalWeight }
}
private val areChildrenBalanced: Boolean by lazy {
children.map { it.totalWeight }.distinct().size == 1
}
}