Solved Part 2.
Change-Id: I5c3cab0446cb4761f9f6b97cc111b132da168475
This commit is contained in:
parent
1f9f6a69ea
commit
8115b1c8ae
@ -78,7 +78,7 @@ hdj{m>838:A,pv}
|
||||
|
||||
data class RuleCondition(val attr: Int = 0, val isSmaller: Boolean = false, val value: Int = 0, val follow: String)
|
||||
|
||||
fun part1(input: List<String>): Int {
|
||||
fun createMap(input: List<String>): Pair<Int, Map<String, List<RuleCondition>>> {
|
||||
val ruleMap = HashMap<String, List<RuleCondition>>()
|
||||
var p = 0
|
||||
do {
|
||||
@ -102,10 +102,16 @@ hdj{m>838:A,pv}
|
||||
if (input[p].isBlank()) break
|
||||
p++
|
||||
} while (true)
|
||||
return p to ruleMap
|
||||
}
|
||||
|
||||
fun part1(input: List<String>): Int {
|
||||
val (p, ruleMap) = createMap(input)
|
||||
var sum = 0
|
||||
for (pp in p + 1 until input.size) {
|
||||
val attrs = input[pp].split("=", ",", "x", "m", "a", "s", "{", "}").filter { it.isNotBlank() }.map { it.toInt() }.toIntArray()
|
||||
val attrs =
|
||||
input[pp].split("=", ",", "x", "m", "a", "s", "{", "}").filter { it.isNotBlank() }.map { it.toInt() }
|
||||
.toIntArray()
|
||||
var ruleId = "in"
|
||||
while (ruleId != "A" && ruleId != "R") {
|
||||
val conditions = ruleMap[ruleId]!!
|
||||
@ -130,74 +136,49 @@ hdj{m>838:A,pv}
|
||||
return sum
|
||||
}
|
||||
|
||||
fun part2(input: List<String>): Long {
|
||||
val ruleMap = HashMap<String, List<RuleCondition>>()
|
||||
var p = 0
|
||||
do {
|
||||
"([a-z]+)\\{(.*)}".toRegex().matchEntire(input[p])?.destructured
|
||||
?.let { (id, rules) ->
|
||||
val rulesList = rules.split(",").map {
|
||||
if (it.contains("<")) {
|
||||
val (attr, rest) = it.split("<")
|
||||
val (value, branchId) = rest.split(":")
|
||||
RuleCondition("xmas".indexOf(attr), true, value.toInt(), branchId)
|
||||
} else if (it.contains(">")) {
|
||||
val (attr, rest) = it.split(">")
|
||||
val (value, branchId) = rest.split(":")
|
||||
RuleCondition("xmas".indexOf(attr), false, value.toInt(), branchId)
|
||||
} else {
|
||||
RuleCondition(follow = it)
|
||||
}
|
||||
}
|
||||
ruleMap[id] = rulesList
|
||||
}
|
||||
if (input[p].isBlank()) break
|
||||
p++
|
||||
} while (true)
|
||||
var prod = 1L
|
||||
for (attridx in 0..3) {
|
||||
var numaccept = 0
|
||||
for (attrvalue in 1..4000) {
|
||||
val destRules = HashSet<String>()
|
||||
val destRulesWithCond = HashSet<String>()
|
||||
val ruleQueue = ArrayDeque<String>()
|
||||
val ruleWithCondQueue = ArrayDeque<String>()
|
||||
ruleQueue.add("in")
|
||||
var rejected = false
|
||||
while (ruleQueue.isNotEmpty()) {
|
||||
val ruleId = ruleQueue.removeFirst()
|
||||
if (ruleId == "R" || ruleId == "A") continue
|
||||
val conditions = ruleMap[ruleId]!!
|
||||
for (cond in conditions) {
|
||||
if (cond.value != 0 && cond.attr == attridx) {
|
||||
val accept = if (cond.isSmaller) {
|
||||
attrvalue < cond.value
|
||||
} else {
|
||||
attrvalue > cond.value
|
||||
}
|
||||
if (accept) {
|
||||
if (!destRulesWithCond.contains(cond.follow)) {
|
||||
destRules.add(cond.follow)
|
||||
destRulesWithCond.add(cond.follow)
|
||||
ruleQueue.add(cond.follow)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!destRules.contains(cond.follow)) {
|
||||
destRules.add(cond.follow)
|
||||
ruleQueue.add(cond.follow)
|
||||
}
|
||||
if (destRulesWithCond.contains(ruleId)) {
|
||||
destRulesWithCond.add(cond.follow)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (destRulesWithCond.contains("A")) numaccept++
|
||||
}
|
||||
prod *= numaccept
|
||||
fun recurse(ruleMap: Map<String, List<RuleCondition>>, ranges: List<IntRange>, ruleId: String): Long {
|
||||
if (ruleId == "A") {
|
||||
return ranges.map { (it.last - it.first + 1).coerceAtLeast(0).toLong() }.reduce(Long::times)
|
||||
}
|
||||
return prod
|
||||
if (ruleId == "R") return 0
|
||||
var result = 0L
|
||||
val conditions = ruleMap[ruleId]!!
|
||||
var currRanges = ranges
|
||||
for (cond in conditions) {
|
||||
if (cond.value != 0) {
|
||||
if (cond.isSmaller) {
|
||||
val subRange = currRanges.mapIndexed { index, intRange ->
|
||||
if (index != cond.attr) intRange else
|
||||
IntRange(intRange.first, intRange.last.coerceAtMost(cond.value - 1))
|
||||
}
|
||||
result += recurse(ruleMap, subRange, cond.follow)
|
||||
currRanges = currRanges.mapIndexed { index, intRange ->
|
||||
if (index != cond.attr) intRange else
|
||||
IntRange(intRange.first.coerceAtLeast(cond.value), intRange.last)
|
||||
}
|
||||
} else {
|
||||
val subRange = currRanges.mapIndexed { index, intRange ->
|
||||
if (index != cond.attr) intRange else
|
||||
IntRange(intRange.first.coerceAtLeast(cond.value + 1), intRange.last)
|
||||
}
|
||||
result += recurse(ruleMap, subRange, cond.follow)
|
||||
currRanges = currRanges.mapIndexed { index, intRange ->
|
||||
if (index != cond.attr) intRange else
|
||||
IntRange(intRange.first, intRange.last.coerceAtMost(cond.value))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result += recurse(ruleMap, currRanges, cond.follow)
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun part2(input: List<String>): Long {
|
||||
val (_, ruleMap) = createMap(input)
|
||||
val ranges = listOf(IntRange(1, 4000), IntRange(1, 4000), IntRange(1, 4000), IntRange(1, 4000))
|
||||
return recurse(ruleMap, ranges, "in")
|
||||
}
|
||||
|
||||
// test if implementation meets criteria from the description, like:
|
||||
|
Loading…
Reference in New Issue
Block a user