Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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)

AltStyle によって変換されたページ (->オリジナル) /