Skip to content

Commit ed24e39

Browse files
committed
2024-24 Refactoring
1 parent 1b447be commit ed24e39

File tree

1 file changed

+20
-80
lines changed

1 file changed

+20
-80
lines changed

scala2/src/main/scala/jurisk/adventofcode/y2024/Advent24.scala

+20-80
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ object Advent24 extends IOApp.Simple {
2323
type Input = (Map[Wire, Boolean], Connections)
2424

2525
sealed trait Wire extends Product with Serializable
26-
object Wire {
26+
private object Wire {
2727
final case class X(i: Int) extends Wire {
2828
override def toString: String = f"x$i%02d"
2929
}
@@ -62,27 +62,26 @@ object Advent24 extends IOApp.Simple {
6262
def parse(s: String): Connections =
6363
Connections.fromIterable(s.splitLines.toSet map Connection.parse)
6464

65-
private def fromIterable(set: Iterable[Connection]): Connections =
65+
private def fromIterable(set: Iterable[(Connection, Wire)]): Connections =
6666
new Connections(
6767
set
68-
.groupBy(_.out)
68+
.groupBy { case (_, out) => out }
6969
.view
7070
.mapValues { connections =>
7171
assert(connections.size == 1)
72-
connections.head
72+
val (connection, _) = connections.head
73+
connection
7374
}
7475
.toMap
7576
)
7677
}
7778

7879
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
8081
val allOutputs: Set[Wire] = map.keySet
8182

8283
def foreach(f: Connection => Unit): Unit = map.values foreach f
8384

84-
def -(c: Connection): Connections = new Connections(map - c.out)
85-
8685
// 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.
8786
private def errorsOnAddition: Int = {
8887
def errorsAddingBit(bit: Int): Int = {
@@ -129,8 +128,8 @@ object Advent24 extends IOApp.Simple {
129128
private def isValid: Boolean = topologicallySortedWires.isDefined
130129

131130
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)
134133
}
135134

136135
val graph = GraphAlgorithms.createAdjacencyMapDirected(edges.toSeq)
@@ -146,65 +145,18 @@ object Advent24 extends IOApp.Simple {
146145
values
147146
} else {
148147
val connection = map(wire)
149-
values + (connection.out -> connection.result(values))
148+
values + (wire -> connection.result(values))
150149
}
151150
}
152151
}
153152

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-
201153
private def swapOutputs(swap: SetOfTwo[Wire]): Connections = {
202154
val (a, b) = swap.tupleInArbitraryOrder
203155
val aC = map(a)
204156
val bC = map(b)
205157
val newMap = map ++ Map(
206-
a -> bC.copy(out = a),
207-
b -> aC.copy(out = b),
158+
a -> bC,
159+
b -> aC,
208160
)
209161
new Connections(newMap)
210162
}
@@ -231,8 +183,8 @@ object Advent24 extends IOApp.Simple {
231183
val candidates = swaps.flatMap(_.toSet).map(Wire.parse).toIndexedSeq
232184
// val candidates = current.allOutputs
233185
(for {
234-
aIdx <- 0 until candidates.size
235-
bIdx <- 0 until candidates.size
186+
aIdx <- candidates.indices
187+
bIdx <- candidates.indices
236188
if aIdx < bIdx
237189
a = candidates(aIdx)
238190
b = candidates(bIdx)
@@ -257,9 +209,7 @@ object Advent24 extends IOApp.Simple {
257209
}
258210
}
259211

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) {
263213
def result(values: Map[Wire, Boolean]): Boolean = {
264214
val aV = values.getOrElse(a, false)
265215
val bV = values.getOrElse(b, false)
@@ -270,11 +220,6 @@ object Advent24 extends IOApp.Simple {
270220
}
271221
}
272222

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-
278223
def name: String = s"$a ${op.name} $b"
279224
}
280225

@@ -293,7 +238,7 @@ object Advent24 extends IOApp.Simple {
293238

294239
private object Connection {
295240
private val RegEx = "(\\w+) (\\w+) (\\w+) -> (\\w+)".r
296-
def parse(s: String): Connection =
241+
def parse(s: String): (Connection, Wire) =
297242
s match {
298243
case RegEx(a, op, b, out) =>
299244
val operation: Operation = op match {
@@ -307,12 +252,13 @@ object Advent24 extends IOApp.Simple {
307252
val lowest = List(a, b).min
308253
val highest = List(a, b).max
309254

310-
Connection(
255+
val connection = Connection(
311256
Wire.parse(lowest),
312257
Wire.parse(highest),
313258
operation,
314-
Wire.parse(out),
315259
)
260+
val output = Wire.parse(out)
261+
(connection, output)
316262
case _ => s.failedToParse
317263
}
318264
}
@@ -346,12 +292,12 @@ object Advent24 extends IOApp.Simple {
346292
}
347293
.mkString("\n\n")
348294

349-
val ops = connections.map.values map { connection =>
295+
val ops = connections.map map { case (out, connection) =>
350296
val opName = s""""${connection.name}""""
351297
s"""
352298
| ${connection.a} -> $opName
353299
| ${connection.b} -> $opName
354-
| $opName -> ${connection.out}
300+
| $opName -> $out
355301
|
356302
|""".stripMargin
357303
}
@@ -385,14 +331,8 @@ object Advent24 extends IOApp.Simple {
385331
def fileName(suffix: String): String =
386332
s"2024/24$suffix.txt"
387333

388-
private val DebugWrite = false
389334
override def run: IO[Unit] = for {
390335
(wires, connections) <- IO(parseFile(fileName("")))
391-
_ <- DebugWrite.whenA {
392-
val (fixed, _) = connections.fix
393-
val simplified = fixed.simplify
394-
debugWrite(simplified)
395-
}
396336
_ <- IO.println(s"Part 1: ${part1((wires, connections))}")
397337
_ <- IO.println(s"Part 2: ${part2((wires, connections))}")
398338
} yield ()

0 commit comments

Comments
 (0)