-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday07p1.py
More file actions
executable file
·116 lines (95 loc) · 3.3 KB
/
day07p1.py
File metadata and controls
executable file
·116 lines (95 loc) · 3.3 KB
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env python
import re
# Global dict (I know, I know..)
wires = dict()
class CircuitNode(object):
oper = None
value = None
final_value = None
left = None
right = None
def __init__(self, name, **kwargs):
self.name = name
if 'oper' in kwargs:
self.oper = kwargs['oper']
if self.oper == 'NOT':
try:
self.right = kwargs['right']
except KeyError:
raise RuntimeError('Missing right node for NOT')
else:
try:
self.left = kwargs['left']
self.right = kwargs['right']
except KeyError as exc:
raise RuntimeError('Missing %s node for %s'
% (exc, self.oper))
elif 'value' in kwargs:
self.value = kwargs['value']
else:
raise RuntimeError('Malformed data for circuit node')
def __repr__(self):
if self.value:
return '<Wire "%s": Value="%s">' % (self.name, self.value)
else: # self.oper must exist
return '<Wire "%s": Oper="%s" Left="%r" Right="%r">' \
% (self.name, self.oper, self.left, self.right)
def calculate(self):
# Short-circuit already calculated nodes
if self.final_value:
return self.final_value
if self.value:
try:
result = int(self.value)
except ValueError:
result = wires[self.value].calculate()
else: # self.oper must exist
if self.left: # Need to check for case of NOT
try:
left_operand = int(self.left)
except ValueError:
left_operand = wires[self.left].calculate()
try:
right_operand = int(self.right)
except ValueError:
right_operand = wires[self.right].calculate()
if self.oper == 'NOT':
result = ~right_operand
elif self.oper == 'AND':
result = left_operand & right_operand
elif self.oper == 'OR':
result = left_operand | right_operand
elif self.oper == 'LSHIFT':
result = left_operand << right_operand
elif self.oper == 'RSHIFT':
result = left_operand >> right_operand
self.final_value = result
return result
with open('input/day07.txt') as fh:
data = fh.read().rstrip('\n').split('\n')
pat1 = re.compile(r'(\w+) -> (\w+)')
pat2 = re.compile(r'(\w+) (\w+) (\w+) -> (\w+)')
pat3 = re.compile(r'(NOT) (\w+) -> (\w+)')
for line in data:
m = re.match(pat1, line)
if m:
name = m.group(2)
wires[name] = CircuitNode(name, value=m.group(1))
continue
m = re.match(pat2, line)
if m:
name = m.group(4)
oper = m.group(2)
wires[name] = CircuitNode(
name, oper=oper, left=m.group(1), right=m.group(3)
)
continue
m = re.match(pat3, line)
if m:
name = m.group(3)
oper = m.group(1)
wires[name] = CircuitNode(name, oper=oper, right=m.group(2))
continue
else:
raise RuntimeError('Bad or malformed line')
print wires['a'].calculate()