11package eu .sim642 .adventofcode2024
22
3+ import scala .annotation .tailrec
34import scala .collection .mutable
45
56object Day24 {
@@ -15,18 +16,23 @@ object Day24 {
1516 case Gate (lhs : String , op : Op , rhs : String )
1617 }
1718
19+ class CyclicCircuit extends RuntimeException
20+
1821 case class Circuit (wireMap : Map [String , Wire ]) {
1922 def zValue : Long = {
2023 val memo = mutable.Map .empty[String , Boolean ]
2124
22- def evalName (name : String ): Boolean =
23- memo.getOrElseUpdate(name, evalWire(wireMap(name)))
25+ def evalName (name : String , called : Set [String ]): Boolean =
26+ if (called.contains(name))
27+ throw new CyclicCircuit
28+ else
29+ memo.getOrElseUpdate(name, evalWire(wireMap(name), called + name))
2430
25- def evalWire (wire : Wire ): Boolean = wire match {
31+ def evalWire (wire : Wire , called : Set [ String ] ): Boolean = wire match {
2632 case Wire .Input (value) => value
2733 case Wire .Gate (lhs, op, rhs) =>
28- val left = evalName(lhs)
29- val right = evalName(rhs)
34+ val left = evalName(lhs, called )
35+ val right = evalName(rhs, called )
3036 op match {
3137 case Op .And => left && right
3238 case Op .Or => left || right
@@ -39,10 +45,30 @@ object Day24 {
3945 .toSeq
4046 .sorted
4147 .foldRight(0L )({ case (zName, acc) =>
42- acc << 1 | (if (evalName(zName)) 1 else 0 )
48+ acc << 1 | (if (evalName(zName, Set .empty )) 1 else 0 )
4349 })
4450 }
4551
52+ def dependencies (name : String ): Set [String ] = {
53+ val memo = mutable.Map .empty[String , Set [String ]]
54+
55+ def evalName (name : String , called : Set [String ]): Set [String ] =
56+ if (called.contains(name))
57+ throw new CyclicCircuit
58+ else
59+ memo.getOrElseUpdate(name, evalWire(wireMap(name), called + name) + name)
60+
61+ def evalWire (wire : Wire , called : Set [String ]): Set [String ] = wire match {
62+ case Wire .Input (value) => Set .empty
63+ case Wire .Gate (lhs, op, rhs) =>
64+ val left = evalName(lhs, called)
65+ val right = evalName(rhs, called)
66+ left ++ right
67+ }
68+
69+ evalName(name, Set .empty)
70+ }
71+
4672 def swapped (name1 : String , name2 : String ): Circuit =
4773 Circuit (wireMap + (name1 -> wireMap(name2)) + (name2 -> wireMap(name1)))
4874
@@ -60,15 +86,75 @@ object Day24 {
6086
6187 def withXValue (value : Long ): Circuit = withInputValue(" x" , value)
6288 def withYValue (value : Long ): Circuit = withInputValue(" y" , value)
89+
90+ def add (xValue : Long , yValue : Long ): Long =
91+ withXValue(xValue).withYValue(yValue).zValue
6392 }
6493
94+ def findWrongBits (circuit : Circuit ): Seq [(String , String )] = {
95+
96+ def isCorrect (circuit : Circuit , i : Int ): Boolean = {
97+ (for {
98+ xBit <- 0 to 3
99+ yBit <- 0 to 3
100+ xValue = xBit.toLong << i >> 1
101+ yValue = yBit.toLong << i >> 1
102+ // if (try {circuit.dependencies("z45"); true} catch {case e: CyclicCircuit => false})
103+ } yield try {circuit.add(xValue, yValue) == xValue + yValue} catch {case e : CyclicCircuit => false }).forall(identity)
104+ }
105+
106+ def helper (circuit : Circuit , i : Int , acc : Seq [(String , String )]): Seq [Seq [(String , String )]] = {
107+ if (acc.sizeIs > 4 )
108+ Seq .empty
109+ else if (i > 44 )
110+ Seq (acc)
111+ else if (isCorrect(circuit, i))
112+ helper(circuit, i + 1 , acc)
113+ else {
114+ println(i)
115+ val depsPrev = circuit.dependencies(s " z ${i - 1 }" )
116+ val deps = circuit.dependencies(s " z $i" )
117+ val depsNext = circuit.dependencies(s " z ${i + 1 }" )
118+ val depsNext2 = circuit.dependencies(s " z ${i + 2 }" )
119+ val wrong1 = ((deps -- depsPrev) ++ (depsNext -- deps)).filterNot(_.startsWith(" x" )).filterNot(_.startsWith(" y" ))
120+ val wrong2 = (depsNext2 -- depsPrev).filterNot(_.startsWith(" x" )).filterNot(_.startsWith(" y" ))
121+ println(wrong1)
122+ println(wrong2)
123+ val swaps =
124+ for {
125+ name1 <- wrong1
126+ name2 <- wrong2
127+ minName = if (name1 < name2) name1 else name2
128+ maxName = if (name1 < name2) name2 else name1
129+ } yield (minName, maxName)
130+ for {
131+ (name1, name2) <- swaps.toSeq
132+ // name2 <- wrong2
133+ newCircuit = circuit.swapped(name1, name2)
134+ // () = println((name1, name2))
135+ if isCorrect(newCircuit, i - 1 )
136+ if isCorrect(newCircuit, i)
137+ swap = (name1, name2)
138+ rest <- helper(newCircuit, i + 1 , acc :+ swap)
139+ } yield rest
140+ }
141+ }
142+
143+ val all = helper(circuit, 0 , Seq .empty)
144+ all.foreach(println)
145+ all.head
146+ }
147+
148+ def findWrongBitsString (circuit : Circuit ): String =
149+ findWrongBits(circuit).flatMap({ case (a, b) => Seq (a, b)}).sorted.mkString(" ," )
150+
65151 def parseInput (s : String ): (String , Wire .Input ) = s match {
66152 case s " $name: 0 " => name -> Wire .Input (false )
67153 case s " $name: 1 " => name -> Wire .Input (true )
68154 }
69155
70156 def parseGate (s : String ): (String , Wire .Gate ) = s match {
71- case s " $lhs AND $rhs -> $name" => name -> Wire .Gate (lhs, Op .And , rhs)
157+ case s " $lhs AND $rhs -> $name" => name -> Wire .Gate (lhs, Op .And , rhs)
72158 case s " $lhs OR $rhs -> $name" => name -> Wire .Gate (lhs, Op .Or , rhs)
73159 case s " $lhs XOR $rhs -> $name" => name -> Wire .Gate (lhs, Op .Xor , rhs)
74160 }
@@ -100,15 +186,16 @@ object Day24 {
100186 def main (args : Array [String ]): Unit = {
101187 val circuit = parseCircuit(input)
102188 println(circuit.zValue)
189+ findWrongBits(circuit)
103190 val circuit2 = circuit.swapped(" z21" , " nhn" ).swapped(" tvb" , " khg" ).swapped(" z33" , " gst" ).swapped(" z12" , " vdc" )
104- printCircuitDot(circuit2)
105- println(circuit2.zValue)
106- println(" 51401618891888" )
191+ // printCircuitDot(circuit2)
192+ // println(circuit2.zValue)
193+ // println("51401618891888")
107194
108195 val circuit3 = circuit2.withXValue(0 )
109- println(circuit3.zValue)
196+ // println(circuit3.zValue)
110197
111- println(Seq (" z21" , " nhn" , " tvb" , " khg" , " z33" , " gst" , " z12" , " vdc" ).sorted.mkString(" ," ))
198+ // println(Seq("z21", "nhn", "tvb", "khg", "z33", "gst", "z12", "vdc").sorted.mkString(","))
112199 // part 2: gst,khg,nhn,tvb,vdc,z12,z21,z33 - correct
113200 }
114201}
0 commit comments