@@ -21,8 +21,8 @@ class Duet : AdventOfCode<Long>(2017, 18) {
2121 override fun part2 (input : List <String >): Long = runBlocking {
2222 val channel0 = Channel <Long >(UNLIMITED )
2323 val channel1 = Channel <Long >(UNLIMITED )
24- val program0 = Program (input, 0 , channel0, channel1)
25- val program1 = Program (input, 1 , channel1, channel0)
24+ val program0 = Program (input, channel0, channel1, mapOf ( P_REGISTER to 0 , PROGRAM_NUMBER_REGISTER to 0 ) )
25+ val program1 = Program (input, channel1, channel0, mapOf ( P_REGISTER to 1 , PROGRAM_NUMBER_REGISTER to 1 ) )
2626
2727 val job0 = launch { program0.run () }
2828 val job1 = launch { program1.run () }
@@ -75,6 +75,11 @@ fun List<String>.parseInstructions(
7575 Add (register, value.toValue())
7676 }
7777
78+ " sub" -> {
79+ val (register, value) = parameters.split(" " )
80+ Sub (register, value.toValue())
81+ }
82+
7883 " mul" -> {
7984 val (register, value) = parameters.split(" " )
8085 Multiply (register, value.toValue())
@@ -92,6 +97,11 @@ fun List<String>.parseInstructions(
9297 JumpIfGreaterZero (value.toValue(), offset.toValue())
9398 }
9499
100+ " jnz" -> {
101+ val (value, offset) = parameters.split(" " )
102+ JumpIfNotZero (value.toValue(), offset.toValue())
103+ }
104+
95105 else -> error(" unknown instruction: $it " )
96106 }
97107}
@@ -114,9 +124,11 @@ sealed interface Value {
114124 }
115125}
116126
127+ private const val P_REGISTER = " p"
117128private const val PROGRAM_NUMBER_REGISTER = " programNumber"
118129private const val LAST_PLAYED_SOUND_REGISTER = " lastPlayedSound"
119130private const val NUMBER_OF_SENDS_REGISTER = " numberOfSends"
131+ private const val NUMBER_OF_MULTIPLY_REGISTER = " numberOfMultiply"
120132
121133sealed interface Instruction {
122134 suspend fun executeOn (registers : MutableMap <String , Long >): Long
@@ -154,9 +166,18 @@ sealed interface Instruction {
154166 }
155167 }
156168
169+ data class Sub (private val register : String , val value : Value ) : Instruction {
170+ override suspend fun executeOn (registers : MutableMap <String , Long >): Long {
171+ registers[register] = registers.getValue(register) - value.toNumber(registers)
172+ return registers.getValue(register)
173+ }
174+ }
175+
157176 data class Multiply (private val register : String , val value : Value ) : Instruction {
158177 override suspend fun executeOn (registers : MutableMap <String , Long >): Long {
159178 registers[register] = registers.getValue(register) * value.toNumber(registers)
179+ val numberOfMultiplies = registers.getValue(NUMBER_OF_MULTIPLY_REGISTER ) + 1
180+ registers[NUMBER_OF_MULTIPLY_REGISTER ] = numberOfMultiplies
160181 return registers.getValue(register)
161182 }
162183 }
@@ -186,33 +207,42 @@ sealed interface Instruction {
186207 }
187208 }
188209
189- data class JumpIfGreaterZero (private val value : Value , private val offset : Value ) : Instruction {
210+ sealed interface Jump : Instruction
211+
212+ data class JumpIfGreaterZero (private val value : Value , private val offset : Value ) : Jump {
190213 override suspend fun executeOn (registers : MutableMap <String , Long >): Long {
191214 if (value.toNumber(registers) > 0 ) {
192215 return offset.toNumber(registers)
193216 }
194217 return 1
195218 }
196219 }
220+
221+ data class JumpIfNotZero (private val value : Value , private val offset : Value ) : Jump {
222+ override suspend fun executeOn (registers : MutableMap <String , Long >): Long {
223+ if (value.toNumber(registers) != 0L ) {
224+ return offset.toNumber(registers)
225+ }
226+ return 1
227+ }
228+ }
197229}
198230
199231class Program (
200232 input : List <String >,
201- programNumber : Long = 0 ,
202233 sendChannel : Channel <Long >? = null ,
203234 receiveChannel : Channel <Long >? = null ,
235+ presetRegisters : Map <String , Long > = emptyMap()
204236) {
205237 var isReceiving = false
238+ private set
206239
207240 private val instructions = input.parseInstructions(sendChannel, receiveChannel)
208- private val registers = mutableMapOf (
209- " p" to programNumber,
210- PROGRAM_NUMBER_REGISTER to programNumber,
211- ).withDefault { 0 }
241+ private val registers = presetRegisters.toMutableMap().withDefault { 0 }
212242 private var instructionPointer = 0L
213243
214244 suspend fun run (): Long {
215- println (" program ${registers[ PROGRAM_NUMBER_REGISTER ] } started" )
245+ println (" program ${registers.getValue( PROGRAM_NUMBER_REGISTER ) } started" )
216246 while (instructionPointer in instructions.indices) {
217247 val instruction = instructions[instructionPointer.toIntChecked()]
218248 if (instruction is Receive ) {
@@ -224,15 +254,17 @@ class Program(
224254 println (" program ${registers[PROGRAM_NUMBER_REGISTER ]} : instruction \" Recover\" with register not zero -> terminating" )
225255 return result
226256 }
227- instructionPointer + = if (instruction is JumpIfGreaterZero ) {
257+ instructionPointer + = if (instruction is Jump ) {
228258 result
229259 } else {
230260 1L
231261 }
232262 }
233- println (" program ${registers[ PROGRAM_NUMBER_REGISTER ] } : instruction pointer ran out of bounds: $instructionPointer -> terminating" )
263+ println (" program ${registers.getValue( PROGRAM_NUMBER_REGISTER ) } : instruction pointer ran out of bounds: $instructionPointer -> terminating" )
234264 return - 1L
235265 }
236266
237267 fun getNumberOfSends (): Long = registers.getValue(NUMBER_OF_SENDS_REGISTER )
268+ fun getNumberOfMultiplies (): Long = registers.getValue(NUMBER_OF_MULTIPLY_REGISTER )
269+ fun getRegisterValue (register : String ): Long = registers.getValue(register)
238270}
0 commit comments