70 lines
1.8 KiB
Python
70 lines
1.8 KiB
Python
|
VERBOSE = True
|
||
|
def verbose(s = "", *args, **kwargs):
|
||
|
if VERBOSE:
|
||
|
print(s, *args, **kwargs)
|
||
|
|
||
|
def get_input(sample = False, part = 1):
|
||
|
with open(f'sample_p{part}' if sample else 'input', 'r') as f:
|
||
|
tmp = f.readlines()
|
||
|
ret = {"start": tmp[0].strip(), "alphabet": {}, "rules": {}}
|
||
|
|
||
|
for line in tmp[2:]:
|
||
|
line = line.strip().split(" -> ")
|
||
|
l, r = line[0], line[1]
|
||
|
for c in l:
|
||
|
ret["alphabet"][c] = 0
|
||
|
ret["alphabet"][r] = 0
|
||
|
ret["rules"][l] = r
|
||
|
return ret
|
||
|
|
||
|
|
||
|
def result(inp, part = 1, steps = 10, ret_len = False, ret_state = False):
|
||
|
res = 0;
|
||
|
alph = inp["alphabet"]
|
||
|
rules = inp["rules"]
|
||
|
state = {k: 0 for k in rules.keys()}
|
||
|
|
||
|
s = inp["start"]
|
||
|
for c in s:
|
||
|
alph[c] += 1
|
||
|
|
||
|
for i, c in enumerate(s[:-1]):
|
||
|
state[s[i] + s[i+1]] += 1
|
||
|
|
||
|
|
||
|
# for k, v in state.items():
|
||
|
# if v > 0:
|
||
|
# verbose(k)
|
||
|
|
||
|
for _ in range(steps):
|
||
|
verbose(f"step {_}")
|
||
|
if _ == 3:
|
||
|
verbose(sum(alph.values()))
|
||
|
for k, v in state.items():
|
||
|
if v > 0:
|
||
|
verbose(k, v)
|
||
|
new_state = {k: 0 for k in rules.keys()}
|
||
|
for k, v in state.items():
|
||
|
if v > 0:
|
||
|
r = rules[k]
|
||
|
new_state[k[0] + r] += v
|
||
|
new_state[r + k[1]] += v
|
||
|
verbose(f"\tadding {r}")
|
||
|
alph[r] += v
|
||
|
state = new_state.copy()
|
||
|
|
||
|
verbose(f"{len(alph) = }")
|
||
|
|
||
|
res = max(alph.values())- min(alph.values())
|
||
|
if ret_state:
|
||
|
return {k: v for k, v in state.items() if v > 0}
|
||
|
if ret_len:
|
||
|
return sum(alph.values())
|
||
|
|
||
|
return res
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
VERBOSE = False
|
||
|
print(result(get_input(), part = 2, steps = 40))
|