Spaces:
Running
Running
File size: 3,443 Bytes
a4da721 |
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 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
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)
|