-
Notifications
You must be signed in to change notification settings - Fork 0
/
2319.py
127 lines (109 loc) · 3.31 KB
/
2319.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
F = 0
r1, r2 = 0, 0
A = []
from collections import defaultdict
import math # part 2
def DBG_( Dict ):
for k,v in Dict.items(): print(k,v)
print()
def Printer(*args):
for arg in args: print(arg, end=' ')
print('')
D = defaultdict(list)
flow, todo, up, down = [],[],None,None
with open('19.' + str(F)) as file:
up, down = [_.split('\n') for _ in file.read().strip().split('\n\n')]
#up = ['ex{x>10:one,m<20:two,a>30:R,A}']
for line in up:
name, rules = line.split('{')
rules = rules.split(',')
end, rules = rules[-1][:-1], rules[:-1]
# Printer('got:',name,end,'rules:',len(rules),rules)
for rule in rules:
cond, dest = rule.split(':')
key, op, val = cond[0],cond[1],int(cond[2:])
# Printer("rule:",key,op,val,dest)
D[name].append([ key, op, val, dest ])
D[name].append(end)
DBG_( D )
for line in down:
flow = defaultdict(int)
line = line[1:-1].split(',')
for xpr in line:
key, val = xpr.split('=')
flow[key] = int(val)
res = None
curr = 'in'
found = False
while not found:
for line in D[curr]:
good = False
if isinstance(line, str):
if line in 'AR':
res = line
found = True
break
curr = line
else:
key, op, val, dest = line
if op == '>':
good = flow[key] > val
elif op == '<':
good = flow[key] < val
else:
die('wtf')
if good:
if dest in 'AR':
res = dest
found = True
break
curr = dest
break
if found and res == 'A':
r1 += sum(flow.values())
Printer("part 1:", r1)
# Part 2
instructions = [
('in', [range(1,4001)] * 4)
]
AC = 0
while instructions :
inst = instructions.pop(0)
curr, rangex4 = inst
if curr in 'AR':
if curr == 'A': # case: R/ do nothing and pass; A/ add :in all combinations
lengths = [len(_) for _ in rangex4]
lengths_product = 1
for n in lengths: lengths_product *= n
AC += lengths_product
continue
*conditions, endpoint = D[curr]
for key, op, val, dest in conditions:
idx = 'xmas'.index(key)
_range = rangex4[ idx ]
if val not in _range:
continue
# split in half
# make a range Object (1/2): prepare 2 slice each of which: [2]int
L,R = [None]*2, [None]*2
if op == '>':
L = [ _range.start, val + 1 ]
R = [ val + 1, _range.stop ]
L,R = R,L
elif op == '<':
L = [ _range.start, val ]
R = [ val, _range.stop ]
else:
die('wtf')
# create a range object (2/2) : L and R are now objects of type range
idx = 'xmas'.index(key)
L, R = range(*L),range(*R)
updated_range_x4 = [_ for _ in rangex4]
updated_range_x4[idx] = L
instructions.append( (dest, updated_range_x4) )
rangex4[idx] = R
instructions.append ( (endpoint, rangex4) )
r2 = AC
Printer("part 2:", r2)
assert(r1 in [19114, 353553])
assert(r2 in [124615747767410, 167409079868000])