fun Map.regValue(r: String): Long = r.toLongOrNull() ?: this.getOrDefault(r, 0) suspend fun part2(instructions: List, progId: Int, incoming: Channel, outgoing: Channel): Int { var ptr = 0 val registers = mutableMapOf() registers.set("p", progId.toLong()) var sent = 0 loop@ while (ptr >= 0 && ptr < instructions.size) { val instruction = instructions[ptr] val elements = instruction.split(" ") val op = elements[0] val a = elements[1] val b = if (elements.size > 2) registers.regValue(elements[2]) else 0 when (op) { "set" -> registers.set(a, b) "add" -> registers.set(a, registers.regValue(a) + b) "mul" -> registers.set(a, registers.regValue(a) * b) "mod" -> registers.set(a, registers.regValue(a) % b) "snd" -> outgoing.send(registers.regValue(a)).also { sent++ } "rcv" -> try { registers.set(a, withTimeout(1000) { incoming.receive() }) // Assume timeout will only occur on Deadlock. } catch (e: TimeoutCancellationException) { println("Reached Deadlock") break@loop } "jgz" -> if (registers.regValue(a) > 0L) { ptr += b.toInt() - 1 // Shift Pointer Back 1 more so that normal increment is accounted for. } } ptr++ } return sent } fun main(args: Array) { val instructions = input.split("\n") println(part1(instructions)) runBlocking { val channel0to1 = Channel(UNLIMITED) val channel1to0 = Channel(UNLIMITED) val prog0 = async { part2(instructions, 0, channel0to1, channel1to0) } val prog1 = async { part2(instructions, 1, channel1to0, channel0to1) } println("Answer is : ${prog1.await()}") } }