2018-12-12 - Subterranean Sustainability
(original .ipynb)
puzzle_input_str = open("puzzle_input/day12.txt").read()
def parse_input(input_str):
state_str, rules_str = input_str.split("\n\n")
state = state_str[15:]
rules = []
for rule_str in rules_str.split("\n"):
pattern_str, result = rule_str.split(" => ")
rules.append(([s for s in pattern_str], result))
return state, rules
def new_pot_contents(i, state, rules):
for rule, result in rules:
if rule == state[i-2:i+3]:
return result
return state[i]
def try_calc_pattern(generation, offset, state):
count_lead = True
lead = -offset
count = 0
for p in state:
if count_lead and p == ".":
lead += 1
if p == "#":
count_lead = False
count +=1
print(generation, lead, count)
def apply_rules(state_str, rules, generations):
offset = 3
state = [".", ".", "."] + [c for c in state_str] + [".", ".", "."]
g = 0
while g < generations:
new_state = []
for i, pot in enumerate(state):
if i < 2 or i+2 >= len(state):
# first or last couple won't change ... I think
new_state.append(pot)
else:
new_state.append(new_pot_contents(i, state, rules))
if new_state[-1] == "#" or new_state[-2] == "#" or new_state[-3] == "#":
new_state += [".", ".", "."]
if new_state[0] == "#" or new_state[1] == "#" or new_state[2] == "#":
offset += 3
new_state = [".", ".", "."] + new_state
state = new_state
g += 1
if g % 1_000 == 0:
try_calc_pattern(g, offset, state)
count = 0
for i, pot in enumerate(new_state):
if pot == "#":
count += (i - offset)
return count
def part_one(input_str, generations):
initial_state, rules = parse_input(input_str)
return apply_rules(initial_state, rules, generations)
print("part one:", part_one(puzzle_input_str, 20))
part one: 3405
# ok so the pattern eventually stabilizes to repeating "..#..#..#.." with a bunch of leading "."s
# so we need to find at at generation 50bn:
# 1. how many leading "."s we grow by every N generations
# 2. how many pots it stabilizes
#
# so I added some code to print this out every 1k generations - let's run the sim
# for a few thousand and see what it looks like
initial_state, rules = parse_input(puzzle_input_str)
apply_rules(initial_state, rules, 3_000)
1000 901 67
2000 1901 67
3000 2901 67
201000
# so it looks like the first plant is at index (n_generation - 99), and there are 67 altogether
# spaced out in every third pot, so
generations = 50_000_000_000
plants = 67
total = 0
generation = generations - 99
while plants > 0:
total += generation
generation += 3
plants -= 1
print("part two:", total)
part two: 3350000000000