Solved Part 2.

Change-Id: I5c3cab0446cb4761f9f6b97cc111b132da168475
This commit is contained in:
Chris Hodges 2023-12-19 15:28:31 +01:00
parent 1f9f6a69ea
commit 8115b1c8ae

View File

@ -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)
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)
}
}
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
if (ruleId == "R") return 0
var result = 0L
val conditions = ruleMap[ruleId]!!
var currRanges = ranges
for (cond in conditions) {
if (cond.value != 0 && cond.attr == attridx) {
val accept = if (cond.isSmaller) {
attrvalue < cond.value
} else {
attrvalue > cond.value
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))
}
if (accept) {
if (!destRulesWithCond.contains(cond.follow)) {
destRules.add(cond.follow)
destRulesWithCond.add(cond.follow)
ruleQueue.add(cond.follow)
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 {
if (!destRules.contains(cond.follow)) {
destRules.add(cond.follow)
ruleQueue.add(cond.follow)
}
if (destRulesWithCond.contains(ruleId)) {
destRulesWithCond.add(cond.follow)
result += recurse(ruleMap, currRanges, cond.follow)
break
}
}
return result
}
}
if (destRulesWithCond.contains("A")) numaccept++
}
prod *= numaccept
}
return prod
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: