AdventOfCode/2017/18/solution_part2.py

138 lines
4.2 KiB
Python

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))