@@ -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
0 commit comments