Advertisement
Guest User

Untitled

a guest
Dec 19th, 2023
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 3.69 KB | Source Code | 0 0
  1. fun part1() {
  2.     val inSorter = Sorter(input[0], "in")
  3.     val parts = input[1].map { Part(it) }
  4.     val accepted = parts.filter { inSorter.isAccepted(it) }
  5.     println("Part 1 :" +  accepted.sumBy { it.partsValue })
  6. }
  7.  
  8. fun part2() {
  9.     val inSorter = Sorter(input[0], "in")
  10.     val accepted = inSorter.numberOfAccepted(listOf(1..4000, 1..4000, 1..4000, 1..4000))
  11.     println("Part 2 :" +  accepted)
  12. }
  13.  
  14. class Sorter(configuration: List<String>, name: String) {
  15.     val line = configuration.find { it.startsWith("$name{") } ?: name
  16.     val rules =
  17.         if (line.length == 1) emptyList() else line.substring((name.length + 1) until line.length - 1).split(",")
  18.             .map { rule -> Rule(rule, configuration) }
  19.  
  20.     fun isAccepted(part: Part):Boolean {
  21.         return when (line) {
  22.             "A" -> true
  23.             "R" -> false
  24.             else -> rules.first { it.matches(part) }.sorter.isAccepted(part)
  25.         }
  26.     }
  27.  
  28.     fun numberOfAccepted(ranges: List<IntRange>): Long {
  29.         if (line == "R") return 0L
  30.         if (line == "A") {
  31.             return ranges[0].length * ranges[1].length * ranges[2].length * ranges[3].length
  32.         }
  33.         var count = 0L
  34.         rules.fold(ranges) { them, rule ->
  35.             val splitParts = rule.splitParts(them)
  36.             count += rule.sorter.numberOfAccepted(splitParts.first)
  37.             splitParts.second
  38.         }
  39.         return count
  40.     }
  41. }
  42.  
  43. class Rule(rule: String, configuration: List<String>) {
  44.     val sorter: Sorter
  45.     val matches: (Part) -> Boolean
  46.     val splitParts: (List<IntRange>) -> Pair<List<IntRange>, List<IntRange>>
  47.  
  48.     init {
  49.         val less = rule.contains("<")
  50.         val more = rule.contains(">")
  51.         if (less || more) {
  52.             val ruleParts = rule.split("<", ">", ":")
  53.             val type = ruleParts[0]
  54.             val test = ruleParts[1].toInt() + if (more) 1 else 0
  55.             sorter = Sorter(configuration, ruleParts[2])
  56.             matches = { part ->
  57.                 val value = when (type) {
  58.                     "x" -> part.x
  59.                     "m" -> part.m
  60.                     "a" -> part.a
  61.                     else -> part.s
  62.                 }
  63.                 if (less) value < test else value > test
  64.             }
  65.             splitParts = {ranges ->
  66.                 val split = when (type) {
  67.                     "x" -> listOf(ranges[0].first until test, ranges[1], ranges[2], ranges[3]) to
  68.                             listOf(test .. ranges[0].last, ranges[1], ranges[2], ranges[3])
  69.  
  70.                     "m" -> listOf(ranges[0], ranges[1].first until test, ranges[2], ranges[3]) to
  71.                             listOf(ranges[0], test .. ranges[1].last, ranges[2], ranges[3])
  72.  
  73.                     "a" -> listOf(ranges[0], ranges[1], ranges[2].first until test, ranges[3]) to
  74.                             listOf(ranges[0], ranges[1], test .. ranges[2].last, ranges[3])
  75.  
  76.                     else -> listOf(ranges[0], ranges[1], ranges[2], ranges[3].first until test) to
  77.                             listOf(ranges[0], ranges[1], ranges[2], test .. ranges[3].last)
  78.                 }
  79.                 if (less) split else split.second to split.first
  80.             }
  81.         } else {
  82.             sorter = Sorter(configuration, rule)
  83.             matches = { _ -> true }
  84.             splitParts = { listOfRanges -> listOfRanges to emptyList() }
  85.         }
  86.     }
  87. }
  88.  
  89. class Part(part: String) {
  90.     val parts = part.replace("[^,0-9]".toRegex(), "").split(",").map { it.toInt() }
  91.     val x = parts[0]
  92.     val m = parts[1]
  93.     val a = parts[2]
  94.     val s = parts[3]
  95.     val partsValue = x + m + a + s
  96. }
  97.  
  98. private val IntRange.length: Long
  99.     get() = (this.last - this.first).toLong() + 1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement