Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- fun part1() {
- val inSorter = Sorter(input[0], "in")
- val parts = input[1].map { Part(it) }
- val accepted = parts.filter { inSorter.isAccepted(it) }
- println("Part 1 :" + accepted.sumBy { it.partsValue })
- }
- fun part2() {
- val inSorter = Sorter(input[0], "in")
- val accepted = inSorter.numberOfAccepted(listOf(1..4000, 1..4000, 1..4000, 1..4000))
- println("Part 2 :" + accepted)
- }
- class Sorter(configuration: List<String>, name: String) {
- val line = configuration.find { it.startsWith("$name{") } ?: name
- val rules =
- if (line.length == 1) emptyList() else line.substring((name.length + 1) until line.length - 1).split(",")
- .map { rule -> Rule(rule, configuration) }
- fun isAccepted(part: Part):Boolean {
- return when (line) {
- "A" -> true
- "R" -> false
- else -> rules.first { it.matches(part) }.sorter.isAccepted(part)
- }
- }
- fun numberOfAccepted(ranges: List<IntRange>): Long {
- if (line == "R") return 0L
- if (line == "A") {
- return ranges[0].length * ranges[1].length * ranges[2].length * ranges[3].length
- }
- var count = 0L
- rules.fold(ranges) { them, rule ->
- val splitParts = rule.splitParts(them)
- count += rule.sorter.numberOfAccepted(splitParts.first)
- splitParts.second
- }
- return count
- }
- }
- class Rule(rule: String, configuration: List<String>) {
- val sorter: Sorter
- val matches: (Part) -> Boolean
- val splitParts: (List<IntRange>) -> Pair<List<IntRange>, List<IntRange>>
- init {
- val less = rule.contains("<")
- val more = rule.contains(">")
- if (less || more) {
- val ruleParts = rule.split("<", ">", ":")
- val type = ruleParts[0]
- val test = ruleParts[1].toInt() + if (more) 1 else 0
- sorter = Sorter(configuration, ruleParts[2])
- matches = { part ->
- val value = when (type) {
- "x" -> part.x
- "m" -> part.m
- "a" -> part.a
- else -> part.s
- }
- if (less) value < test else value > test
- }
- splitParts = {ranges ->
- val split = when (type) {
- "x" -> listOf(ranges[0].first until test, ranges[1], ranges[2], ranges[3]) to
- listOf(test .. ranges[0].last, ranges[1], ranges[2], ranges[3])
- "m" -> listOf(ranges[0], ranges[1].first until test, ranges[2], ranges[3]) to
- listOf(ranges[0], test .. ranges[1].last, ranges[2], ranges[3])
- "a" -> listOf(ranges[0], ranges[1], ranges[2].first until test, ranges[3]) to
- listOf(ranges[0], ranges[1], test .. ranges[2].last, ranges[3])
- else -> listOf(ranges[0], ranges[1], ranges[2], ranges[3].first until test) to
- listOf(ranges[0], ranges[1], ranges[2], test .. ranges[3].last)
- }
- if (less) split else split.second to split.first
- }
- } else {
- sorter = Sorter(configuration, rule)
- matches = { _ -> true }
- splitParts = { listOfRanges -> listOfRanges to emptyList() }
- }
- }
- }
- class Part(part: String) {
- val parts = part.replace("[^,0-9]".toRegex(), "").split(",").map { it.toInt() }
- val x = parts[0]
- val m = parts[1]
- val a = parts[2]
- val s = parts[3]
- val partsValue = x + m + a + s
- }
- private val IntRange.length: Long
- get() = (this.last - this.first).toLong() + 1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement