Skip to content

Commit 5b54798

Browse files
committed
Create Circuit class in 2024 day 24
1 parent 62912a6 commit 5b54798

File tree

2 files changed

+49
-47
lines changed

2 files changed

+49
-47
lines changed

src/main/scala/eu/sim642/adventofcode2024/Day24.scala

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,49 +15,51 @@ object Day24 {
1515
case Gate(lhs: String, op: Op, rhs: String)
1616
}
1717

18-
type Circuit = Map[String, Wire]
18+
case class Circuit(wireMap: Map[String, Wire]) {
19+
def zValue: Long = {
20+
val memo = mutable.Map.empty[String, Boolean]
1921

20-
def getZValue(circuit: Circuit): Long = {
22+
def evalName(name: String): Boolean =
23+
memo.getOrElseUpdate(name, evalWire(wireMap(name)))
2124

22-
val memo = mutable.Map.empty[String, Boolean]
23-
24-
def evalName(name: String): Boolean =
25-
memo.getOrElseUpdate(name, evalWire(circuit(name)))
25+
def evalWire(wire: Wire): Boolean = wire match {
26+
case Wire.Input(value) => value
27+
case Wire.Gate(lhs, op, rhs) =>
28+
val left = evalName(lhs)
29+
val right = evalName(rhs)
30+
op match {
31+
case Op.And => left && right
32+
case Op.Or => left || right
33+
case Op.Xor => left != right
34+
}
35+
}
2636

27-
def evalWire(wire: Wire): Boolean = wire match {
28-
case Wire.Input(value) => value
29-
case Wire.Gate(lhs, op, rhs) =>
30-
val left = evalName(lhs)
31-
val right = evalName(rhs)
32-
op match {
33-
case Op.And => left && right
34-
case Op.Or => left || right
35-
case Op.Xor => left != right
36-
}
37+
wireMap.keys
38+
.filter(_.startsWith("z"))
39+
.toSeq
40+
.sorted
41+
.foldRight(0L)({ case (zName, acc) =>
42+
acc << 1 | (if (evalName(zName)) 1 else 0)
43+
})
3744
}
3845

39-
circuit.keys
40-
.filter(_.startsWith("z"))
41-
.toSeq
42-
.sorted
43-
.foldRight(0L)({ case (zName, acc) =>
44-
acc << 1 | (if (evalName(zName)) 1 else 0)
45-
})
46-
}
46+
def swapped(name1: String, name2: String): Circuit =
47+
Circuit(wireMap + (name1 -> wireMap(name2)) + (name2 -> wireMap(name1)))
48+
49+
private def withInputValue(inputPrefix: String, value: Long): Circuit = {
50+
val (newCircuit, remainingValue) = wireMap.keys
51+
.filter(_.startsWith(inputPrefix))
52+
.toSeq
53+
.sorted
54+
.foldLeft((wireMap, value))({ case ((circuit, value), prefixName) =>
55+
(circuit + (prefixName -> Wire.Input((value & 1) == 1L)), value >> 1)
56+
})
57+
assert(remainingValue == 0)
58+
Circuit(newCircuit)
59+
}
4760

48-
def swap(circuit: Circuit, name1: String, name2: String): Circuit =
49-
circuit + (name1 -> circuit(name2)) + (name2 -> circuit(name1))
50-
51-
def changeInput(circuit: Circuit, prefix: String, value: Long): Circuit = {
52-
val (a, b) = circuit.keys
53-
.filter(_.startsWith(prefix))
54-
.toSeq
55-
.sorted
56-
.foldLeft((circuit, value))({ case ((circuit, value), prefixName) =>
57-
(circuit + (prefixName -> Wire.Input((value & 1) == 1L)), value >> 1)
58-
})
59-
assert(b == 0)
60-
a
61+
def withXValue(value: Long): Circuit = withInputValue("x", value)
62+
def withYValue(value: Long): Circuit = withInputValue("y", value)
6163
}
6264

6365
def parseInput(s: String): (String, Wire.Input) = s match {
@@ -75,12 +77,12 @@ object Day24 {
7577
case s"$inputs\n\n$gates" =>
7678
val inputMap = inputs.linesIterator.map(parseInput).toMap
7779
val gateMap = gates.linesIterator.map(parseGate).toMap
78-
inputMap ++ gateMap
80+
Circuit(inputMap ++ gateMap)
7981
}
8082

8183
def printCircuitDot(circuit: Circuit): Unit = {
8284
println("digraph circuit {")
83-
for ((name, wire) <- circuit) {
85+
for ((name, wire) <- circuit.wireMap) {
8486
wire match {
8587
case Wire.Input(value) =>
8688
println(s" $name;")
@@ -97,14 +99,14 @@ object Day24 {
9799

98100
def main(args: Array[String]): Unit = {
99101
val circuit = parseCircuit(input)
100-
println(getZValue(circuit))
101-
val circuit2 = swap(swap(swap(swap(circuit, "z21", "nhn"), "tvb", "khg"), "z33", "gst"), "z12", "vdc")
102+
println(circuit.zValue)
103+
val circuit2 = circuit.swapped("z21", "nhn").swapped("tvb", "khg").swapped("z33", "gst").swapped("z12", "vdc")
102104
printCircuitDot(circuit2)
103-
println(getZValue(circuit2))
105+
println(circuit2.zValue)
104106
println("51401618891888")
105107

106-
val circuit3 = changeInput(changeInput(circuit2, "x", 0), "asdasd", 0)
107-
println(getZValue(circuit3))
108+
val circuit3 = circuit2.withXValue(0)
109+
println(circuit3.zValue)
108110

109111
println(Seq("z21", "nhn", "tvb", "khg", "z33", "gst", "z12", "vdc").sorted.mkString(","))
110112
// part 2: gst,khg,nhn,tvb,vdc,z12,z21,z33 - correct

src/test/scala/eu/sim642/adventofcode2024/Day24Test.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ class Day24Test extends AnyFunSuite {
6767
|tnw OR pbm -> gnj""".stripMargin
6868

6969
test("Part 1 examples") {
70-
assert(getZValue(parseCircuit(exampleInput)) == 4)
71-
assert(getZValue(parseCircuit(exampleInput2)) == 2024)
70+
assert(parseCircuit(exampleInput).zValue == 4)
71+
assert(parseCircuit(exampleInput2).zValue == 2024)
7272
}
7373

7474
test("Part 1 input answer") {
75-
assert(getZValue(parseCircuit(input)) == 51410244478064L)
75+
assert(parseCircuit(input).zValue == 51410244478064L)
7676
}
7777
}

0 commit comments

Comments
 (0)