1- package de.ronny_h.aoc.year24.day17
2-
31import de.ronny_h.aoc.AdventOfCode
42import kotlin.math.pow
53import kotlin.properties.Delegates
@@ -8,10 +6,23 @@ fun main() = ChronospatialComputer().run("4,1,7,6,4,1,0,2,7", "TODO")
86
97class ChronospatialComputer : AdventOfCode <String >(2024 , 17 ) {
108 override fun part1 (input : List <String >): String {
11- return ThreeBitComputer ().runProgram(input )
9+ return ThreeBitComputer (input ).runProgram().joinToString( " , " )
1210 }
1311
14- override fun part2 (input : List <String >): String = " TODO"
12+ override fun part2 (input : List <String >): String {
13+ val computer = ThreeBitComputer (input)
14+ val initState = computer.save()
15+ var registerA = 0L
16+ println (" ${computer.program} ${computer.program.size} " )
17+ while (computer.runProgram() != computer.program) {
18+ registerA++
19+ if (registerA % 1000000 == 0L ) {
20+ println (" $registerA - ${computer.getOutputList()} ${computer.getOutputList().size} " )
21+ }
22+ computer.restore(initState, registerA)
23+ }
24+ return " $registerA "
25+ }
1526}
1627
1728/* *
@@ -38,50 +49,53 @@ class ChronospatialComputer : AdventOfCode<String>(2024, 17) {
3849 * 6 bdv division of A and 2^<combo operand>, truncated result in B
3950 * 7 cdv division of A and 2^<combo operand>, truncated result in C
4051 */
41- private class ThreeBitComputer {
52+ private class ThreeBitComputer ( input : List < String >) {
4253
4354 private val instructionStep = 2
4455
45- private lateinit var program: List < Int >
46- private var registerA by Delegates .notNull< Int >( )
47- private var registerB by Delegates .notNull< Int >( )
48- private var registerC by Delegates .notNull< Int >( )
56+ val program = input.readProgram()
57+ private var registerA = input.readRegister( ' A ' )
58+ private var registerB = input.readRegister( ' B ' )
59+ private var registerC = input.readRegister( ' C ' )
4960 private var instructionPointer = 0
5061
5162 private val output = mutableListOf<Int >()
5263
53- fun init (input : List <String >) {
54- program = input.readProgram()
55- registerA = input.readRegister(' A' )
56- registerB = input.readRegister(' B' )
57- registerC = input.readRegister(' C' )
58- instructionPointer = 0
59- output.clear()
60- }
64+ fun getOutputList (): List <Int > = output
6165
6266 private val instructions: List < (Int ) -> Unit > = listOf (
63- { op -> registerA = (registerA / 2.0 .pow( combo(op))).toInt() ; next() }, // 0 adv
64- { op -> registerB = (registerB xor op) ; next() }, // 1 bxl
67+ { op -> registerA = (registerA shr combo(op).toIntChecked()) ; next() }, // 0 adv; A/2^x = A shr x
68+ { op -> registerB = (registerB xor op.toLong()) ; next() }, // 1 bxl
6569 { op -> registerB = (combo(op) % 8 ) and 7 ; next() }, // 2 bst; 7=111 -> take only lowest 3 bits
66- { op -> if (registerA == 0 ) next() else instructionPointer = op }, // 3 jnz
70+ { op -> if (registerA == 0L ) next() else instructionPointer = op }, // 3 jnz
6771 { _ -> registerB = (registerB xor registerC) ; next() }, // 4 bxc
68- { op -> output.add((combo(op) % 8 ) and 7 ) ; next() }, // 5 out
69- { op -> registerB = (registerA / 2.0 .pow( combo(op))).toInt( ); next() }, // 6 bdv
70- { op -> registerC = (registerA / 2.0 .pow( combo(op))).toInt( ); next() }, // 7 cdv
72+ { op -> output.add((( combo(op) % 8 ) and 7 ).toInt()) ; next() }, // 5 out
73+ { op -> registerB = (registerA shr combo(op).toIntChecked() ); next() }, // 6 bdv
74+ { op -> registerC = (registerA shr combo(op).toIntChecked() ); next() }, // 7 cdv
7175 )
7276
73- fun runProgram (input : List <String >): String {
74- init (input)
77+ fun runProgram (): List <Int > {
7578 while (instructionPointer < program.size) {
7679 val instruction = program[instructionPointer]
7780 val op = program[instructionPointer + 1 ]
7881 instructions[instruction].invoke(op)
7982 }
80- return output.joinToString(" ," )
83+ return output
84+ }
85+
86+ fun save () = State (registerA, registerB, registerC, instructionPointer)
87+ fun restore (state : State , registerAOverride : Long ) {
88+ this .registerA = registerAOverride
89+ this .registerB = state.registerB
90+ this .registerC = state.registerC
91+ this .instructionPointer = state.instructionPointer
92+ this .output.clear()
8193 }
8294
8395 private fun combo (op : Int ) = when (op) {
84- in 1 .. 3 -> op
96+ 1 -> 1L
97+ 2 -> 2L
98+ 3 -> 3L
8599 4 -> registerA
86100 5 -> registerB
87101 6 -> registerC
@@ -95,11 +109,25 @@ private class ThreeBitComputer {
95109 private fun List<String>.readRegister (register : Char ) =
96110 first { it.startsWith(" Register $register : " ) }
97111 .substringAfter(" Register $register : " )
98- .toInt ()
112+ .toLong ()
99113
100114 private fun List<String>.readProgram () =
101115 first { it.startsWith(" Program: " ) }
102116 .substringAfter(" Program: " )
103117 .split(" ," )
104118 .map(String ::toInt)
119+
120+ data class State (
121+ val registerA : Long ,
122+ val registerB : Long ,
123+ val registerC : Long ,
124+ val instructionPointer : Int ,
125+ )
126+ }
127+
128+ private fun Long.toIntChecked (): Int {
129+ if (this > Int .MAX_VALUE ) {
130+ throw IllegalArgumentException (" $this exceeds Int range" )
131+ }
132+ return this .toInt()
105133}
0 commit comments