Skip to content

Commit e56725c

Browse files
committed
Added day 2017-18
1 parent eadcc9d commit e56725c

File tree

1 file changed

+191
-0
lines changed

1 file changed

+191
-0
lines changed

2017/18-Duet.py

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
# -------------------------------- Input data -------------------------------- #
2+
import os
3+
4+
test_data = {}
5+
6+
test = 1
7+
test_data[test] = {"input": """set a 1
8+
add a 2
9+
mul a a
10+
mod a 5
11+
snd a
12+
set a 0
13+
rcv a
14+
jgz a -1
15+
set a 1
16+
jgz a -2""",
17+
"expected": ['4', 'Unknown'],
18+
}
19+
test += 1
20+
test_data[test] = {"input": """snd 1
21+
snd 2
22+
snd p
23+
rcv a
24+
rcv b
25+
rcv c
26+
rcv d""",
27+
"expected": ['4', 'Unknown'],
28+
}
29+
30+
test = 'real'
31+
input_file = os.path.join(os.path.dirname(__file__), 'Inputs', os.path.basename(__file__).replace('.py', '.txt'))
32+
test_data[test] = {"input": open(input_file, "r+").read().strip(),
33+
"expected": ['7071', 'Unknown'],
34+
}
35+
36+
# -------------------------------- Control program execution -------------------------------- #
37+
38+
case_to_test = 'real'
39+
part_to_test = 2
40+
verbose_level = 1
41+
42+
# -------------------------------- Initialize some variables -------------------------------- #
43+
44+
puzzle_input = test_data[case_to_test]['input']
45+
puzzle_expected_result = test_data[case_to_test]['expected'][part_to_test-1]
46+
puzzle_actual_result = 'Unknown'
47+
48+
49+
# -------------------------------- Actual code execution -------------------------------- #
50+
51+
def val_get (registers, value):
52+
try:
53+
return int(value)
54+
except ValueError:
55+
return registers[value]
56+
57+
58+
def computer (instructions, program_id):
59+
global verbose_level, puzzle_actual_result
60+
i = 0
61+
registers = {'p': program_id}
62+
while i < len(instructions):
63+
instr = instructions[i]
64+
65+
if verbose_level == 3:
66+
print (program_id, instr)
67+
68+
if instr[0] == 'snd':
69+
if verbose_level == 2:
70+
print (program_id, i, instr, 'sending', val_get(registers, instr[1]), registers)
71+
72+
if program_id == 1:
73+
puzzle_actual_result += 1
74+
yield val_get(registers, instr[1])
75+
elif instr[0] == 'set':
76+
registers.update({instr[1]: val_get(registers, instr[2])})
77+
elif instr[0] == 'add':
78+
registers.setdefault(instr[1], 0)
79+
registers[instr[1]] += val_get(registers, instr[2])
80+
elif instr[0] == 'mul':
81+
registers.setdefault(instr[1], 0)
82+
registers[instr[1]] *= val_get(registers, instr[2])
83+
elif instr[0] == 'mod':
84+
registers.setdefault(instr[1], 0)
85+
registers[instr[1]] %= val_get(registers, instr[2])
86+
elif instr[0] == 'rcv':
87+
registers.setdefault(instr[1], 0)
88+
registers[instr[1]] = yield None
89+
if verbose_level == 2:
90+
print (program_id, i, instr, 'received', registers[instr[1]], registers)
91+
elif instr[0] == 'jgz':
92+
if val_get(registers, instr[1]) > 0:
93+
i += val_get(registers, instr[2]) - 1
94+
95+
i += 1
96+
97+
98+
99+
if part_to_test == 1:
100+
instructions = [(string.split(' ')) for string in puzzle_input.split('\n')]
101+
102+
i = 0
103+
registers = {}
104+
playing = 0
105+
while i < len(instructions):
106+
instr = instructions[i]
107+
108+
if instr[0] == 'snd':
109+
playing = val_get(registers, instr[1])
110+
elif instr[0] == 'set':
111+
registers.update({instr[1]: val_get(registers, instr[2])})
112+
elif instr[0] == 'add':
113+
registers.setdefault(instr[1], 0)
114+
registers[instr[1]] += val_get(registers, instr[2])
115+
elif instr[0] == 'mul':
116+
registers.setdefault(instr[1], 0)
117+
registers[instr[1]] *= val_get(registers, instr[2])
118+
elif instr[0] == 'mod':
119+
registers.setdefault(instr[1], 0)
120+
registers[instr[1]] %= val_get(registers, instr[2])
121+
elif instr[0] == 'rcv':
122+
if val_get(registers, instr[1]):
123+
puzzle_actual_result = playing
124+
break
125+
elif instr[0] == 'jgz':
126+
if val_get(registers, instr[1]):
127+
i += val_get(registers, instr[2]) - 1
128+
129+
i += 1
130+
131+
132+
else:
133+
instructions = [(string.split(' ')) for string in puzzle_input.split('\n')]
134+
135+
i = 0
136+
registers = {}
137+
playing = 0
138+
program = {x: computer(instructions, x) for x in range(2)}
139+
reception = {x: [] for x in range(2)}
140+
start = True
141+
stalled = {x:False for x in range(2)}
142+
prog = 0
143+
puzzle_actual_result = 0
144+
145+
while (len(reception[0]) + len(reception[1])) > 0 or start:
146+
start = False
147+
if stalled[prog] and len(reception[prog]):
148+
result = program[prog].send(reception[prog].pop(0))
149+
stalled[prog] = False
150+
elif not stalled[prog]:
151+
result = next(program[prog])
152+
else:
153+
break
154+
155+
if verbose_level == 2:
156+
print ('main received', result, 'from', prog)
157+
158+
while result is not None or len(reception[prog]) > 0:
159+
if result is None:
160+
if verbose_level == 2:
161+
print ('main sends', reception[prog][0], 'to', prog)
162+
result = program[prog].send(reception[prog].pop(0))
163+
else:
164+
reception[1-prog].append(result)
165+
result = next(program[prog])
166+
167+
if verbose_level == 2:
168+
print ('main received', result, 'from', prog)
169+
170+
stalled[prog] = True
171+
172+
if verbose_level == 3:
173+
print (reception)
174+
elif verbose_level == 2:
175+
print (len(reception[0]), len(reception[1]), puzzle_actual_result)
176+
177+
prog = 1 - prog
178+
179+
180+
181+
182+
# -------------------------------- Outputs / results -------------------------------- #
183+
184+
if verbose_level >= 3:
185+
print ('Input : ' + puzzle_input)
186+
print ('Expected result : ' + str(puzzle_expected_result))
187+
print ('Actual result : ' + str(puzzle_actual_result))
188+
189+
190+
191+

0 commit comments

Comments
 (0)