-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathaoc07.py
97 lines (71 loc) · 2.08 KB
/
aoc07.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""Some Assembly Required
Advent of Code 2015, day 7
Solution by Geir Arne Hjelle, 2016-12-04
"""
# Standard library imports
import pathlib
import sys
# Third party imports
import numpy as np
COMMANDS = dict(
NOT=lambda x: ~x,
AND=lambda x, y: x & y,
OR=lambda x, y: x | y,
LSHIFT=lambda x, s: x << s,
RSHIFT=lambda x, s: x >> s,
)
SIGNALS = {}
def read_circuit(filename):
circuit = {}
with open(filename, mode="r") as fid:
for line in fid:
connection, output = [w.strip() for w in line.split("->")]
circuit[output] = connection
return circuit
def read_signals(circuit):
for wire, signal in circuit.copy().items():
try:
SIGNALS[wire] = _parse_signal(signal)
del circuit[wire]
except (TypeError, IndexError):
pass
def _parse_signal(signal):
value = SIGNALS.get(signal, _int(signal))
if value is None:
words = signal.split()
command = words.pop(-2)
value = COMMANDS[command](*[SIGNALS.get(w, _int(w)) for w in words])
return value
def _int(string):
"""Convert to uint16 without ValueErrors, because dict.get() does not handle
errors very gracefully...
"""
try:
return np.uint16(string)
except ValueError:
return None
def main(args):
"""Solve the problem for all file paths"""
for file_path in [pathlib.Path(p) for p in args if not p.startswith("-")]:
solve(file_path)
def solve(file_path):
"""Solve the problem for one file path"""
print(f"\n{file_path}:")
# Part 1
circuit = read_circuit(file_path)
while circuit:
read_signals(circuit)
signal_a = SIGNALS.get("a")
for wire, signal in sorted(SIGNALS.items()):
del SIGNALS[wire]
print(f"The signal at a is {signal_a}")
if signal_a is None:
return
# Part 2
circuit = read_circuit(file_path)
circuit["b"] = signal_a
while circuit:
read_signals(circuit)
print(f"The modified signal at a is {SIGNALS.get('a')}")
if __name__ == "__main__":
main(sys.argv[1:])