11package eu .sim642 .adventofcode2024
22
3+ import com .microsoft .z3 .{Context , Status }
4+
5+ import scala .jdk .CollectionConverters .*
6+
37object Day17 {
48
59 case class Registers (a : Int , b : Int , c : Int )
@@ -8,12 +12,12 @@ object Day17 {
812
913 case class Input (registers : Registers , program : Program )
1014
11- def runOutput (input : Input ): String = {
15+ def runOutput0 (input : Input ): Seq [ Int ] = {
1216 val Input (registers, program) = input
1317
1418 def helper (ip : Int , registers : Registers ): LazyList [Int ] = {
15- println(ip)
16- println(registers)
19+ // println(ip)
20+ // println(registers)
1721
1822 def combo (operand : Int ): Int = operand match {
1923 case 0 | 1 | 2 | 3 => operand
@@ -32,7 +36,8 @@ object Day17 {
3236
3337 program(ip) match {
3438 case 0 => // adv
35- helper(ip + 2 , registers.copy(a = registers.a / (1 << comboOperand)))
39+ // helper(ip + 2, registers.copy(a = registers.a / (1 << comboOperand)))
40+ helper(ip + 2 , registers.copy(a = registers.a >> comboOperand))
3641 case 1 => // bxl
3742 helper(ip + 2 , registers.copy(b = registers.b ^ literalOperand))
3843 case 2 => // bst
@@ -44,17 +49,73 @@ object Day17 {
4449 case 5 => // out
4550 (comboOperand & 0b111 ) +: helper(ip + 2 , registers)
4651 case 6 => // bdv
47- helper(ip + 2 , registers.copy(b = registers.a / (1 << comboOperand)))
52+ // helper(ip + 2, registers.copy(b = registers.a / (1 << comboOperand)))
53+ helper(ip + 2 , registers.copy(b = registers.a >> comboOperand))
4854 case 7 => // cdv
49- helper(ip + 2 , registers.copy(c = registers.a / (1 << comboOperand)))
55+ // helper(ip + 2, registers.copy(c = registers.a / (1 << comboOperand)))
56+ helper(ip + 2 , registers.copy(c = registers.a >> comboOperand))
5057 case _ => throw new IllegalArgumentException (" illegal instruction" )
5158 }
5259 }
5360 else
5461 LazyList .empty
5562 }
5663
57- helper(0 , registers).mkString(" ," )
64+ helper(0 , registers)
65+ }
66+
67+ def runOutput (input : Input ): String = runOutput0(input).mkString(" ," )
68+
69+ def findQuineA (input : Input ): Int = {
70+ Iterator .from(0 )
71+ .find(newA => runOutput0(Input (input.registers.copy(a = newA), input.program)) == input.program)
72+ .get
73+ }
74+
75+ def myProg (initialA : Int , expectedOutputs : Iterator [Int ]): Boolean = {
76+ var a : Int = initialA
77+ var b : Int = 0
78+ var c : Int = 0
79+ while (a != 0 ) {
80+ b = a & 0b111
81+ b = b ^ 1
82+ c = a >> b
83+ b = b ^ 5
84+ b = b ^ c
85+ a = a >> 3
86+ if ((b & 0b111 ) != expectedOutputs.next())
87+ return false
88+ }
89+ ! expectedOutputs.hasNext
90+ }
91+
92+ def findQuineA2 (input : Input ): Int = {
93+ Iterator .from(0 )
94+ .find(newA => myProg(newA, input.program.iterator))
95+ .get
96+ }
97+
98+ def findQuineA3 (input : Input ): Long = {
99+ val ctx = new Context (Map (" model" -> " true" ).asJava)
100+ import ctx ._
101+ val s = mkSolver()
102+
103+ val bits = input.program.size * 3
104+ val initialA = mkBVConst(" initialA" , bits)
105+
106+ for ((instruction, i) <- input.program.zipWithIndex) {
107+ val a = mkBVLSHR(initialA, mkBV(i * 3 , bits))
108+ var b = mkBVAND(a, mkBV(7 , bits))
109+ b = mkBVXOR(b, mkBV(1 , bits))
110+ val c = mkBVLSHR(a, b)
111+ b = mkBVXOR(b, mkBV(5 , bits))
112+ b = mkBVXOR(b, c)
113+ val out = mkBVAND(b, mkBV(7 , bits))
114+ s.add(mkEq(out, mkBV(instruction, bits)))
115+ }
116+
117+ assert(s.check() == Status .SATISFIABLE )
118+ s.getModel.evaluate(initialA, false ).toString.toLong
58119 }
59120
60121 def parseInput (input : String ): Input = input match {
@@ -67,7 +128,25 @@ object Day17 {
67128 lazy val input : String = scala.io.Source .fromInputStream(getClass.getResourceAsStream(" day17.txt" )).mkString.trim
68129
69130 def main (args : Array [String ]): Unit = {
70- println(runOutput(parseInput(input)))
131+ /* var a: Int = 30344604
132+ var b: Int = 0
133+ var c: Int = 0
134+ while (a != 0) {
135+ b = a & 0b111
136+ b = b ^ 1
137+ c = a >> b
138+ b = b ^ 5
139+ b = b ^ c
140+ a = a >> 3
141+ print(b & 0b111)
142+ print(',')
143+ }*/
144+
145+
146+ // println(runOutput(parseInput(input)))
147+ println(findQuineA3(parseInput(input)))
148+
149+ // part 2: 164540892147389 - correct
71150
72151 // part 1: 4,5,0,4,7,4,3,0,0 - wrong (bst used literal not combo operand)
73152 }
0 commit comments