@@ -23,7 +23,7 @@ object Advent24 extends IOApp.Simple {
23
23
type Input = (Map [Wire , Boolean ], Connections )
24
24
25
25
sealed trait Wire extends Product with Serializable
26
- object Wire {
26
+ private object Wire {
27
27
final case class X (i : Int ) extends Wire {
28
28
override def toString : String = f " x $i%02d "
29
29
}
@@ -62,27 +62,26 @@ object Advent24 extends IOApp.Simple {
62
62
def parse (s : String ): Connections =
63
63
Connections .fromIterable(s.splitLines.toSet map Connection .parse)
64
64
65
- private def fromIterable (set : Iterable [Connection ]): Connections =
65
+ private def fromIterable (set : Iterable [( Connection , Wire ) ]): Connections =
66
66
new Connections (
67
67
set
68
- .groupBy(_. out)
68
+ .groupBy { case (_, out) => out }
69
69
.view
70
70
.mapValues { connections =>
71
71
assert(connections.size == 1 )
72
- connections.head
72
+ val (connection, _) = connections.head
73
+ connection
73
74
}
74
75
.toMap
75
76
)
76
77
}
77
78
78
79
final case class Connections private (map : Map [Wire , Connection ]) {
79
- val allWires : Set [Wire ] = map.values. flatMap(_.wiresMentioned) .toSet
80
+ val allWires : Set [Wire ] = map.flatMap { case (k, v) => Set (k, v.a, v.b) } .toSet
80
81
val allOutputs : Set [Wire ] = map.keySet
81
82
82
83
def foreach (f : Connection => Unit ): Unit = map.values foreach f
83
84
84
- def - (c : Connection ): Connections = new Connections (map - c.out)
85
-
86
85
// TODO: This doesn't do a sufficient test, as these bit-by-bit tests don't catch all issues that could happen. Consider adding random numbers.
87
86
private def errorsOnAddition : Int = {
88
87
def errorsAddingBit (bit : Int ): Int = {
@@ -129,8 +128,8 @@ object Advent24 extends IOApp.Simple {
129
128
private def isValid : Boolean = topologicallySortedWires.isDefined
130
129
131
130
private val topologicallySortedWires : Option [List [Wire ]] = {
132
- val edges = map.values .flatMap { c =>
133
- Set (c.a -> c. out, c.b -> c. out)
131
+ val edges = map.toSeq .flatMap { case (out, c) =>
132
+ Set (c.a -> out, c.b -> out)
134
133
}
135
134
136
135
val graph = GraphAlgorithms .createAdjacencyMapDirected(edges.toSeq)
@@ -146,65 +145,18 @@ object Advent24 extends IOApp.Simple {
146
145
values
147
146
} else {
148
147
val connection = map(wire)
149
- values + (connection.out -> connection.result(values))
148
+ values + (wire -> connection.result(values))
150
149
}
151
150
}
152
151
}
153
152
154
- def simplify : Connections = {
155
- def rename (
156
- connections : Set [Connection ],
157
- what : Wire ,
158
- toWhat : Wire ,
159
- ): Set [Connection ] =
160
- connections.map(_.rename(what, toWhat))
161
-
162
- def simplifyBit (
163
- connections : Set [Connection ],
164
- bit : Int ,
165
- ): Set [Connection ] = {
166
-
167
- def simplifyOp (
168
- operation : Operation ,
169
- connections : Set [Connection ],
170
- ): Set [Connection ] =
171
- connections.find {
172
- case Connection (a, b, `operation`, _) =>
173
- Set (a, b) == Set (Wire .X (bit), Wire .Y (bit))
174
- case _ =>
175
- false
176
- } match {
177
- case Some (a @ Connection (_, _, `operation`, out)) =>
178
- rename(
179
- connections - a,
180
- out,
181
- Wire .Debug (f " ${operation.name}_ $bit%02d_ $out" ),
182
- )
183
- case _ =>
184
- println(s " Bit $bit: $operation not found " )
185
- connections
186
- }
187
-
188
- List (Xor , And ).foldLeft(connections) { case (acc, op) =>
189
- simplifyOp(op, acc)
190
- }
191
- }
192
-
193
- Connections .fromIterable {
194
- (0 until InputBits ).foldLeft(map.values.toSet) {
195
- case (connections, bit) =>
196
- simplifyBit(connections, bit)
197
- }
198
- }
199
- }
200
-
201
153
private def swapOutputs (swap : SetOfTwo [Wire ]): Connections = {
202
154
val (a, b) = swap.tupleInArbitraryOrder
203
155
val aC = map(a)
204
156
val bC = map(b)
205
157
val newMap = map ++ Map (
206
- a -> bC.copy(out = a) ,
207
- b -> aC.copy(out = b) ,
158
+ a -> bC,
159
+ b -> aC,
208
160
)
209
161
new Connections (newMap)
210
162
}
@@ -231,8 +183,8 @@ object Advent24 extends IOApp.Simple {
231
183
val candidates = swaps.flatMap(_.toSet).map(Wire .parse).toIndexedSeq
232
184
// val candidates = current.allOutputs
233
185
(for {
234
- aIdx <- 0 until candidates.size
235
- bIdx <- 0 until candidates.size
186
+ aIdx <- candidates.indices
187
+ bIdx <- candidates.indices
236
188
if aIdx < bIdx
237
189
a = candidates(aIdx)
238
190
b = candidates(bIdx)
@@ -257,9 +209,7 @@ object Advent24 extends IOApp.Simple {
257
209
}
258
210
}
259
211
260
- final case class Connection (a : Wire , b : Wire , op : Operation , out : Wire ) {
261
- def wiresMentioned : Set [Wire ] = Set (a, b, out)
262
-
212
+ final case class Connection (a : Wire , b : Wire , op : Operation ) {
263
213
def result (values : Map [Wire , Boolean ]): Boolean = {
264
214
val aV = values.getOrElse(a, false )
265
215
val bV = values.getOrElse(b, false )
@@ -270,11 +220,6 @@ object Advent24 extends IOApp.Simple {
270
220
}
271
221
}
272
222
273
- def rename (what : Wire , toWhat : Wire ): Connection = {
274
- val m = Map (what -> toWhat)
275
- copy(a = replace(a, m), b = replace(b, m), out = replace(out, m))
276
- }
277
-
278
223
def name : String = s " $a ${op.name} $b"
279
224
}
280
225
@@ -293,7 +238,7 @@ object Advent24 extends IOApp.Simple {
293
238
294
239
private object Connection {
295
240
private val RegEx = " (\\ w+) (\\ w+) (\\ w+) -> (\\ w+)" .r
296
- def parse (s : String ): Connection =
241
+ def parse (s : String ): ( Connection , Wire ) =
297
242
s match {
298
243
case RegEx (a, op, b, out) =>
299
244
val operation : Operation = op match {
@@ -307,12 +252,13 @@ object Advent24 extends IOApp.Simple {
307
252
val lowest = List (a, b).min
308
253
val highest = List (a, b).max
309
254
310
- Connection (
255
+ val connection = Connection (
311
256
Wire .parse(lowest),
312
257
Wire .parse(highest),
313
258
operation,
314
- Wire .parse(out),
315
259
)
260
+ val output = Wire .parse(out)
261
+ (connection, output)
316
262
case _ => s.failedToParse
317
263
}
318
264
}
@@ -346,12 +292,12 @@ object Advent24 extends IOApp.Simple {
346
292
}
347
293
.mkString(" \n\n " )
348
294
349
- val ops = connections.map.values map { connection =>
295
+ val ops = connections.map map { case (out, connection) =>
350
296
val opName = s """ " ${connection.name}" """
351
297
s """
352
298
| ${connection.a} -> $opName
353
299
| ${connection.b} -> $opName
354
- | $opName -> ${connection. out}
300
+ | $opName -> $out
355
301
|
356
302
| """ .stripMargin
357
303
}
@@ -385,14 +331,8 @@ object Advent24 extends IOApp.Simple {
385
331
def fileName (suffix : String ): String =
386
332
s " 2024/24 $suffix.txt "
387
333
388
- private val DebugWrite = false
389
334
override def run : IO [Unit ] = for {
390
335
(wires, connections) <- IO (parseFile(fileName(" " )))
391
- _ <- DebugWrite .whenA {
392
- val (fixed, _) = connections.fix
393
- val simplified = fixed.simplify
394
- debugWrite(simplified)
395
- }
396
336
_ <- IO .println(s " Part 1: ${part1((wires, connections))}" )
397
337
_ <- IO .println(s " Part 2: ${part2((wires, connections))}" )
398
338
} yield ()
0 commit comments