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)
|
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>>()
|
val ruleMap = HashMap<String, List<RuleCondition>>()
|
||||||
var p = 0
|
var p = 0
|
||||||
do {
|
do {
|
||||||
@ -102,10 +102,16 @@ hdj{m>838:A,pv}
|
|||||||
if (input[p].isBlank()) break
|
if (input[p].isBlank()) break
|
||||||
p++
|
p++
|
||||||
} while (true)
|
} while (true)
|
||||||
|
return p to ruleMap
|
||||||
|
}
|
||||||
|
|
||||||
|
fun part1(input: List<String>): Int {
|
||||||
|
val (p, ruleMap) = createMap(input)
|
||||||
var sum = 0
|
var sum = 0
|
||||||
for (pp in p + 1 until input.size) {
|
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"
|
var ruleId = "in"
|
||||||
while (ruleId != "A" && ruleId != "R") {
|
while (ruleId != "A" && ruleId != "R") {
|
||||||
val conditions = ruleMap[ruleId]!!
|
val conditions = ruleMap[ruleId]!!
|
||||||
@ -130,74 +136,49 @@ hdj{m>838:A,pv}
|
|||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
fun part2(input: List<String>): Long {
|
fun recurse(ruleMap: Map<String, List<RuleCondition>>, ranges: List<IntRange>, ruleId: String): Long {
|
||||||
val ruleMap = HashMap<String, List<RuleCondition>>()
|
if (ruleId == "A") {
|
||||||
var p = 0
|
return ranges.map { (it.last - it.first + 1).coerceAtLeast(0).toLong() }.reduce(Long::times)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
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:
|
// test if implementation meets criteria from the description, like:
|
||||||
|
Loading…
Reference in New Issue
Block a user