1
1
package adventofcode2023
2
2
3
3
import java.io.File
4
+ import java.util.LinkedList
4
5
5
6
object Day19 {
6
7
private const val ACCEPT = " A"
@@ -41,11 +42,25 @@ object Day19 {
41
42
42
43
private data class Condition (val variable : Char , val checker : Char , val value : Int ) {
43
44
fun check (checked : Map <Char , Int >): Boolean =
45
+ checkValue(checked[variable]!! )
46
+
47
+ fun checkRange (checked : Map <Char , Pair <Int , Int >>): Int =
48
+ (if (checkValue(checked[variable]!! .first)) RANGE_LOWER else 0 ) +
49
+ (if (checkValue(checked[variable]!! .second)) RANGE_HIGHER else 0 )
50
+
51
+ private fun checkValue (checkedValue : Int ): Boolean =
44
52
when (checker) {
45
- ' >' -> checked[variable] !! > value
46
- ' <' -> checked[variable] !! < value
53
+ ' >' -> checkedValue > value
54
+ ' <' -> checkedValue < value
47
55
else -> throw Exception (" Unknown checker" )
48
56
}
57
+
58
+ companion object {
59
+ const val RANGE_NONE = 0
60
+ const val RANGE_LOWER = 1
61
+ const val RANGE_HIGHER = 2
62
+ const val RANGE_BOTH = 3
63
+ }
49
64
}
50
65
51
66
private fun checkPart (part : Map <Char , Int >): Boolean {
@@ -71,9 +86,82 @@ object Day19 {
71
86
throw Exception (" Couldn't check part" )
72
87
}
73
88
89
+ private fun acceptedRanges (): List <Map <Char , Pair <Int , Int >>> {
90
+ // Map of values (x, m, a, s), Workflow name, Workflow step index
91
+ val ranges = LinkedList <Triple <Map <Char , Pair <Int , Int >>, String , Int >> ()
92
+
93
+ val accepted = mutableListOf<Map <Char , Pair <Int , Int >>>()
94
+
95
+ ranges.add(Triple (mapOf (
96
+ ' x' to Pair (1 , 4000 ),
97
+ ' m' to Pair (1 , 4000 ),
98
+ ' a' to Pair (1 , 4000 ),
99
+ ' s' to Pair (1 , 4000 )
100
+ ), STARTING_WORKFLOW , 0 ))
101
+
102
+ while (ranges.isNotEmpty()) {
103
+ val range = ranges.removeFirst()
104
+ val valueRanges = range.first
105
+ val workflowName = range.second
106
+ val stepIndex = range.third
107
+
108
+ when (workflowName) {
109
+ ACCEPT -> {
110
+ accepted.add(valueRanges)
111
+ continue
112
+ }
113
+ REJECT -> continue
114
+ }
115
+
116
+ val step = workflows[workflowName]!! [stepIndex]
117
+
118
+ if (step.first != null ) {
119
+ val condition = step.first!!
120
+ val (variable, _, value) = condition
121
+
122
+ fun createTriple (
123
+ changeWorkflow : Boolean , firstValue : Int = -1, secondValue : Int = -1
124
+ ): Triple <Map <Char , Pair <Int , Int >>, String, Int> {
125
+ val newRangeMap = valueRanges.toMutableMap().apply {
126
+ if (firstValue >= 0 ) this [variable] = this [variable]!! .copy(first = firstValue)
127
+ if (secondValue >= 0 ) this [variable] = this [variable]!! .copy(second = secondValue)
128
+ }
129
+
130
+ return Triple (newRangeMap, if (changeWorkflow) step.second else workflowName, if (changeWorkflow) 0 else stepIndex + 1 )
131
+ }
132
+
133
+ when (condition.checkRange(valueRanges)) {
134
+ Condition .RANGE_NONE -> {
135
+ ranges.add(Triple (valueRanges, workflowName, stepIndex + 1 ))
136
+ }
137
+ Condition .RANGE_LOWER -> {
138
+ ranges.add(createTriple(true , secondValue = value - 1 ))
139
+ ranges.add(createTriple(false , firstValue = value))
140
+ }
141
+ Condition .RANGE_HIGHER -> {
142
+ ranges.add(createTriple(true , firstValue = value + 1 ))
143
+ ranges.add(createTriple(false , secondValue = value))
144
+ }
145
+ Condition .RANGE_BOTH -> {
146
+ ranges.add(Triple (valueRanges, step.second, 0 ))
147
+ }
148
+ }
149
+ } else {
150
+ ranges.add(Triple (valueRanges, step.second, 0 ))
151
+ }
152
+ }
153
+
154
+ return accepted
155
+ }
156
+
74
157
fun part1 () = println (parts.filter { checkPart(it) }.sumOf { it.values.sum() })
158
+
159
+ fun part2 () = println (acceptedRanges().sumOf { ranges ->
160
+ ranges.values.fold(1L ) { acc, pair -> acc * (pair.second - pair.first + 1 ) }
161
+ })
75
162
}
76
163
77
164
fun main () {
78
165
Day19 .part1()
166
+ Day19 .part2()
79
167
}
0 commit comments