import sys,re,asyncio input_f = 'input' def parse_input(input_str): pattern = r"^([a-zA-Z]{3})\s{1}(\w)?\s?(-?\w+)$" match = re.match(pattern, input_str) if match: if match.group(2): return match.group(1),match.group(2),match.group(3) else: return match.group(1),match.group(3) return None def sets_return(value, sets): if value in sets: result = sets[value] if isinstance(result, str) and not value.lstrip('-').isdigit(): return sets_return(result, sets) return result elif value.isdigit() or value.lstrip('-').isdigit(): return int(value) return None async def loop0(instructions,p_0, p_1,sets_0,state): x = 0 while 0 <= x < len(instructions): i = instructions[x] if i[0] == 'set': sets_0[i[1]] = sets_return(i[2],sets_0) x += 1 elif i[0] == 'add': sets_0[i[1]] += sets_return(i[2],sets_0) x += 1 elif i[0] == 'mul': sets_0[i[1]] *= sets_return(i[2],sets_0) x += 1 elif i[0] == 'mod': sets_0[i[1]] %= sets_return(i[2],sets_0) x += 1 elif i[0] == 'snd': await p_1.put(sets_return(i[1],sets_0)) #print('P0 send', sets_0_return(i[1]),sets_0)#,'p_1',p_1) x += 1 elif i[0] == 'rcv': if p_0.empty(): state["loop0_waiting"] = True if state["loop1_waiting"]: # Both loops are stuck print(f"Program exiting. Loop1 'snd' count: {state['count']}") return await asyncio.sleep(0.1) else: state["loop0_waiting"] = False sets_0[i[1]] = await p_0.get() #print('P0 recv', sets_0[i[1]],sets_0)#,'p_0',p_0) x += 1 elif i[0] == 'jgz': if sets_return(i[1],sets_0) > 0: x += sets_return(i[2],sets_0) else: x += 1 await asyncio.sleep(0.01) async def loop1(instructions,p_0, p_1,sets_1,state): x = 0 while 0 <= x < len(instructions): i = instructions[x] if i[0] == 'set': sets_1[i[1]] = sets_return(i[2],sets_1) x += 1 elif i[0] == 'add': sets_1[i[1]] += sets_return(i[2],sets_1) x += 1 elif i[0] == 'mul': sets_1[i[1]] *= sets_return(i[2],sets_1) x += 1 elif i[0] == 'mod': sets_1[i[1]] %= sets_return(i[2],sets_1) x += 1 elif i[0] == 'snd': await p_0.put(sets_return(i[1],sets_1)) state["count"] += 1 print(state["count"]) x += 1 elif i[0] == 'rcv': if p_1.empty(): state["loop1_waiting"] = True if state["loop0_waiting"]: # Both loops are stuck print(f"Program exiting. Loop1 'snd' count: {state['count']}") return await asyncio.sleep(0.1) else: state["loop1_waiting"] = False sets_1[i[1]] = await p_1.get() #print('P1 recv', sets_1[i[1]],sets_1) #,'p_1',p_1) #condition.notify_all() x += 1 elif i[0] == 'jgz': if sets_return(i[1],sets_1) > 0: x += sets_return(i[2],sets_1) else: x += 1 await asyncio.sleep(0.01) async def main(instructions): p_0 = asyncio.Queue() p_1 = asyncio.Queue() sets_0 = {'p': 0} sets_1 = {'p': 1} state = { "loop0_waiting": False, "loop1_waiting": False, "count": 0 } # Create tasks for the two loops #task1 = asyncio.create_task(loop0(instructions[:],p_0,p_1)) #task2 = asyncio.create_task(loop1(count,instructions[:],p_0,p_1)) await asyncio.gather( loop0(instructions, p_0, p_1, sets_0, state), loop1(instructions, p_0, p_1, sets_1, state) ) instructions = [] with open(input_f) as file: for line in file: instructions.append(list(parse_input(line.rstrip()))) asyncio.run(main(instructions))