-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day19.kt
76 lines (67 loc) · 2.59 KB
/
Day19.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
package aoc2020.day19
import java.io.File
// The required depth is 13 for the large input - setting it to 20 as it doesn't affect the performance significantly
var depthLimit = 20
fun readRulesToMap(path: String): Map<String, String> {
val lineList = mutableListOf<String>()
File(path).inputStream().bufferedReader().forEachLine { lineList.add(it) }
val inputMap = mutableMapOf<String, String>()
lineList
.map { it.split(": ") }
.forEach { inputMap[it[0]] = it[1] }
return inputMap
}
fun readMessagesToList(path: String): List<String> {
val lineList = mutableListOf<String>()
File(path).inputStream().bufferedReader().forEachLine { lineList.add(it) }
return lineList
}
fun findRegex(ruleMap: Map<String, String>): String {
return recursivelyReplace("0", ruleMap, 0, false)
}
fun recursivelyReplace(rule: String, map: Map<String, String>, depth: Int, limitDepth: Boolean): String {
val ruleValue = map[rule]
if (ruleValue == "a" || ruleValue == "b") {
return ruleValue
}
if (limitDepth && depth > depthLimit) {
return ""
}
var regex = if (ruleValue!!.contains("|")) "(" else ""
for ((index, split) in ruleValue.split("|").withIndex()) {
val rules = split.trim().split(" ")
for (r in rules) {
val recursivelyReplace = recursivelyReplace(r, map, depth + 1, limitDepth)
regex = "$regex$recursivelyReplace"
}
if (ruleValue.contains("|") && index == 0) {
regex += "|"
}
}
if (ruleValue.contains("|")) regex += ")"
return regex
}
fun countValidMessages(messages: List<String>, regexString: String): Int {
return messages.count { it.matches(Regex(regexString)) }
}
// To avoid infinite loops, limit the depth an infinite rule can reach
fun countValidMessagesV2(messages: List<String>, ruleMap: Map<String, String>): Int {
val regex = recursivelyReplace("0", ruleMap, 0, true)
return messages.count { it.matches(Regex(regex)) }
}
// All rules but 0, 8, 11 are finite
fun testsWithNewRules(rules: Map<String, String>) {
val listOfRulesThatFinish = mutableListOf<String>()
val sortedRules = rules.toSortedMap(compareBy<String> { it.length }.thenBy { it })
for (rule in sortedRules.keys) {
print("Rule $rule started at " + System.currentTimeMillis())
try {
println(" : " + recursivelyReplace(rule, rules, 0, false))
listOfRulesThatFinish.add(rule)
} catch (error: StackOverflowError) {
println(" : stack overflow")
continue
}
}
println(listOfRulesThatFinish)
}