-
Notifications
You must be signed in to change notification settings - Fork 0
/
day7.py
107 lines (86 loc) · 2.51 KB
/
day7.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
98
99
100
101
102
103
104
105
106
107
# vi: set shiftwidth=4 tabstop=4 expandtab:
import datetime
import os
import operator
top_dir = os.path.dirname(os.path.abspath(__file__)) + "/../../"
max_val = 65535
binary_ops = {
" AND ": operator.and_,
" OR ": operator.or_,
" LSHIFT ": operator.lshift,
" RSHIFT ": operator.rshift,
}
unary_ops = {"NOT ": lambda x: max_val - x}
def get_parse_expr(expr):
for bin_name, bin_func in binary_ops.items():
left, mid, right = expr.partition(bin_name)
if mid == bin_name:
return (bin_func, left, right)
for un_name, un_func in unary_ops.items():
if expr.startswith(un_name):
return (un_func, expr[len(un_name) :])
return (expr,)
def get_wire_from_string(s, sep=" -> "):
expr, mid, wire = s.partition(sep)
assert mid == sep
return wire, get_parse_expr(expr)
def get_wires_from_file(file_path=top_dir + "resources/year2015_day7_input.txt"):
with open(file_path) as f:
return dict(get_wire_from_string(l.strip()) for l in f)
def eval_wire(wire, wires):
return eval_wire_(wire, dict(), wires)
def eval_wire_(wire, env, wires):
val = env.get(wire, None)
if val is not None:
return val
expr = wires.get(wire, None)
if expr is None:
ret = int(wire)
elif len(expr) == 3:
func, left, right = expr
ret = func(eval_wire_(left, env, wires), eval_wire_(right, env, wires))
elif len(expr) == 2:
func, value = expr
ret = func(eval_wire_(value, env, wires))
else:
value = expr[0]
ret = eval_wire_(value, env, wires)
env[wire] = ret
return ret
def run_tests():
wires = [
"123 -> x",
"456 -> y",
"x AND y -> d",
"x OR y -> e",
"x LSHIFT 2 -> f",
"y RSHIFT 2 -> g",
"NOT x -> h",
"NOT y -> i",
]
wires = dict(get_wire_from_string(l) for l in wires)
values = {
"d": 72,
"e": 507,
"f": 492,
"g": 114,
"h": 65412,
"i": 65079,
"x": 123,
"y": 456,
}
for name, value in values.items():
assert eval_wire(name, wires) == value
def get_solutions():
wires = get_wires_from_file()
val_a = eval_wire("a", wires)
print(val_a == 16076)
wires["b"] = str(val_a)
val_a2 = eval_wire("a", wires)
print(val_a2 == 2797) # Happens to be wrong ?!
if __name__ == "__main__":
begin = datetime.datetime.now()
run_tests()
get_solutions()
end = datetime.datetime.now()
print(end - begin)