11package eu .sim642 .adventofcode2025
22
3- import eu .sim642 .adventofcodelib .IteratorImplicits .*
4- import com .microsoft .z3 .{ArithExpr , Context , IntExpr , IntSort , Status }
5- import eu .sim642 .adventofcodelib .{GaussianElimination , NumberTheory }
6- import eu .sim642 .adventofcodelib .graph .{BFS , Dijkstra , GraphSearch , TargetNode , UnitNeighbors }
3+ import com .microsoft .z3 .{ArithExpr , Context , IntSort , Status }
4+ import eu .sim642 .adventofcodelib .GaussianElimination
5+ import eu .sim642 .adventofcodelib .graph .{BFS , GraphSearch , TargetNode , UnitNeighbors }
76
8- import scala .collection .mutable
97import scala .jdk .CollectionConverters .*
108
119object Day10 {
@@ -64,7 +62,7 @@ object Day10 {
6462 object Z3Part2Solution extends Part2Solution {
6563 override def fewestPresses (machine : Machine ): Int = {
6664 val ctx = new Context (Map (" model" -> " true" ).asJava)
67- import ctx ._
65+ import ctx .*
6866 val s = mkOptimize()
6967
7068 val buttonPresses = machine.buttons.zipWithIndex.map((_, i) => mkIntConst(s " x $i" ))
@@ -150,6 +148,46 @@ object Day10 {
150148 }
151149 }
152150
151+ /**
152+ * Solution, which reduces parity of joltages to part 1-like problem.
153+ * @see [[https://www.reddit.com/r/adventofcode/comments/1pk87hl/2025_day_10_part_2_bifurcate_your_way_to_victory/ ]]
154+ */
155+ object BifurcatePart2Solution extends Part2Solution {
156+ override def fewestPresses (machine : Machine ): Int = {
157+ def parity (joltages : Joltages ): Lights =
158+ joltages.map(i => if (i % 2 != 0 ) true else false )
159+
160+ val zeroJoltages : Joltages = machine.joltages.map(_ => 0 )
161+ val parityPresses =
162+ machine.buttons.toSet
163+ .subsets()
164+ .map(buttons =>
165+ buttons.foldLeft(zeroJoltages)((acc, button) =>
166+ button.foldLeft(acc)((acc, i) => acc.updated(i, acc(i) + 1 ))
167+ ) -> buttons.size
168+ )
169+ .toSeq
170+ .groupBy((joltages, _) => parity(joltages))
171+ .withDefaultValue(Seq .empty)
172+
173+ def helper (joltages : Joltages ): Option [Int ] = {
174+ if (joltages == zeroJoltages)
175+ Some (0 )
176+ else if (joltages.exists(_ < 0 ))
177+ None
178+ else {
179+ (for {
180+ (pressJoltages, presses) <- parityPresses(parity(joltages))
181+ newJoltages = (joltages lazyZip pressJoltages).map(_ - _).map(_ / 2 )
182+ newPresses <- helper(newJoltages)
183+ } yield 2 * newPresses + presses).minOption
184+ }
185+ }
186+
187+ helper(machine.joltages).get
188+ }
189+ }
190+
153191 def parseMachine (s : String ): Machine = s match {
154192 case s " [ $lightsStr] $buttonsStr { $joltagesStr} " =>
155193 val lights = lightsStr.map(_ == '#' ).toVector
@@ -164,6 +202,6 @@ object Day10 {
164202
165203 def main (args : Array [String ]): Unit = {
166204 println(Part1 .sumFewestPresses(parseMachines(input)))
167- println(GaussianEliminationPart2Solution .sumFewestPresses(parseMachines(input)))
205+ println(BifurcatePart2Solution .sumFewestPresses(parseMachines(input)))
168206 }
169207}
0 commit comments