@@ -15,49 +15,51 @@ object Day24 {
15
15
case Gate (lhs : String , op : Op , rhs : String )
16
16
}
17
17
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 ]
19
21
20
- def getZValue (circuit : Circuit ): Long = {
22
+ def evalName (name : String ): Boolean =
23
+ memo.getOrElseUpdate(name, evalWire(wireMap(name)))
21
24
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
+ }
26
36
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
+ })
37
44
}
38
45
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
+ }
47
60
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)
61
63
}
62
64
63
65
def parseInput (s : String ): (String , Wire .Input ) = s match {
@@ -75,12 +77,12 @@ object Day24 {
75
77
case s " $inputs\n\n $gates" =>
76
78
val inputMap = inputs.linesIterator.map(parseInput).toMap
77
79
val gateMap = gates.linesIterator.map(parseGate).toMap
78
- inputMap ++ gateMap
80
+ Circuit ( inputMap ++ gateMap)
79
81
}
80
82
81
83
def printCircuitDot (circuit : Circuit ): Unit = {
82
84
println(" digraph circuit {" )
83
- for ((name, wire) <- circuit) {
85
+ for ((name, wire) <- circuit.wireMap ) {
84
86
wire match {
85
87
case Wire .Input (value) =>
86
88
println(s " $name; " )
@@ -97,14 +99,14 @@ object Day24 {
97
99
98
100
def main (args : Array [String ]): Unit = {
99
101
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" )
102
104
printCircuitDot(circuit2)
103
- println(getZValue( circuit2) )
105
+ println(circuit2.zValue )
104
106
println(" 51401618891888" )
105
107
106
- val circuit3 = changeInput(changeInput( circuit2, " x " , 0 ), " asdasd " , 0 )
107
- println(getZValue( circuit3) )
108
+ val circuit3 = circuit2.withXValue( 0 )
109
+ println(circuit3.zValue )
108
110
109
111
println(Seq (" z21" , " nhn" , " tvb" , " khg" , " z33" , " gst" , " z12" , " vdc" ).sorted.mkString(" ," ))
110
112
// part 2: gst,khg,nhn,tvb,vdc,z12,z21,z33 - correct
0 commit comments