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