-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday22.py
59 lines (44 loc) · 1.58 KB
/
day22.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
from collections import defaultdict, deque
def day22(inp, only_part1=False):
buyers = list(map(int, inp.splitlines()))
part1 = part2 = 0
prices_by_deltas = defaultdict(dict) # 4-tuple -> {buyer id -> first price}
deltas = deque(maxlen=4)
for buyer_id, buyer in enumerate(buyers):
secret = buyer
for _ in range(2000):
next_secret = evolve(secret)
if only_part1:
# for testing
secret = next_secret
continue
# part 2: record prices
deltas.append(next_secret % 10 - secret % 10)
if len(deltas) == 4:
deltas_key = tuple(deltas)
if buyer_id not in prices_by_deltas[deltas_key]:
prices_by_deltas[deltas_key][buyer_id] = next_secret % 10
secret = next_secret
part1 += secret
if only_part1:
return part1, None
# part 2: find most lucrative sequence
part2 = max(
sum(price_dict.values())
for price_dict in prices_by_deltas.values()
)
return part1, part2
def mix(secret, other):
return secret ^ other
def prune(secret):
return secret % 16777216
def evolve(secret):
secret = prune(mix(secret, secret * 64))
secret = prune(mix(secret, secret // 32))
return prune(mix(secret, secret * 2048))
if __name__ == "__main__":
testinp = open('day22.testinp').read()
testinp2 = open('day22.testinp2').read()
print(day22(testinp, only_part1=True)[0], day22(testinp2)[1])
inp = open('day22.inp').read()
print(day22(inp))