Spaces:
Running
Running
def load_data(file): | |
with open(file) as f: | |
data = f.read() | |
return [int(n) for n in data.split("\n") if len(n) != 0] | |
def mix(secret, value): | |
return secret ^ value | |
def prune(secret): | |
return secret % 16777216 | |
def evolve(secret): | |
# Step 1 | |
secret = prune(mix(secret, secret * 64)) | |
# Step 2 | |
secret = prune(mix(secret, int(secret / 32))) | |
# Step 3 | |
secret = prune(mix(secret, secret * 2048)) | |
return secret | |
def evolve_n_steps(secret, N): | |
for n in range(N): | |
secret = evolve(secret) | |
return secret | |
# file = "test.txt" | |
file = "input.txt" | |
data = load_data(file) | |
results = {secret: evolve_n_steps(secret, 2000) for secret in data} | |
print(sum(results.values())) | |
## Part 2 | |
def get_price(secret): | |
return int(str(secret)[-1]) | |
def get_buying_info(secret, n_steps=2000): | |
prices = [get_price(secret)] | |
secrets = [secret] | |
changes = [None] | |
for _ in range(n_steps): | |
secret = evolve(secret) | |
secrets.append(secret) | |
prices.append(get_price(secret)) | |
changes.append(prices[-1] - prices[-2]) | |
return secrets, prices, changes | |
def get_price_from_pattern(pattern, changes, prices): | |
for idx in range(len(changes) - 3): | |
if changes[idx:idx+4] == pattern: | |
return prices[idx+3] | |
return None | |
def get_max_patterns(changes, prices): | |
patterns = [] | |
max_price = max(prices[5:]) | |
print(max_price) | |
print() | |
for idx in range(4, len(prices) - 3): | |
if prices[idx] == max_price: | |
pattern = tuple(changes[idx-3:idx+1]) | |
patterns.append(pattern) | |
return patterns | |
def get_patterns_at(changes, prices, set_price): | |
patterns = [] | |
for idx in range(4, len(prices) - 3): | |
if prices[idx] == set_price: | |
pattern = tuple(changes[idx-3:idx+1]) | |
patterns.append(pattern) | |
return patterns | |
def get_all_patterns(changes): | |
p = set() | |
for idx in range(1, len(changes) - 4): | |
p.add(tuple(changes[idx:idx+4])) | |
return p | |
from collections import defaultdict | |
# file = "test2.txt" | |
file = "input.txt" | |
data = load_data(file) | |
all_patterns = defaultdict(list) | |
all_prices = {} | |
all_changes = {} | |
for secret in data: | |
secrets, prices, changes = get_buying_info(secret) | |
# max_patterns = set(get_max_patterns(changes, prices)) | |
# max_patterns = set(get_patterns_at(changes, prices, 7)) | |
all_changes[secret] = changes | |
all_prices[secret] = prices | |
patterns = get_all_patterns(changes) | |
# all_patterns.append(p) | |
for p in patterns: | |
all_patterns[p].extend([secret]) | |
pattern_counts = {p: len(s) for p, s in all_patterns.items()} | |
sorted_pattern_counts = sorted(list((pattern_counts.values())))[::-1] # Sorted in ascending order | |
# 200 is kind of arbitrary, there was a bit of guessing and checking involved... | |
top_n_counts = sorted_pattern_counts[:200] | |
# Could speed it up by ordering in order of count | |
possible_patterns = [list(p) for p,c in pattern_counts.items() if c in top_n_counts] | |
max_bananas = 0 | |
for pattern in possible_patterns: | |
bananas = 0 | |
for secret in data: | |
prices = all_prices[secret] | |
changes = all_changes[secret] | |
sell_price = get_price_from_pattern(pattern, changes, prices) | |
if sell_price: | |
bananas += sell_price | |
if bananas >= max_bananas: | |
# print("New max: ", bananas) | |
max_bananas = bananas | |
# | |
print(max_bananas) | |