advent-of-code/2018-python/solutions/day_12.py
2021-11-01 16:45:03 +01:00

66 lines
2.3 KiB
Python

from collections import defaultdict
from solutions import BaseSolution
class Solution(BaseSolution):
input_file = '12.in'
def __str__(self):
return 'Day 12: Subterranean Sustainability'
def solve(self, puzzle_input):
initital_pots, rules = self._prepare(puzzle_input)
pots, _ = self._grow(initital_pots, rules, 20)
return sum(k for k, v in pots.items() if v == '#')
def solve_again(self, puzzle_input):
# No tests cover for this, so here goes an explanation.
#
# To get the sum of the filty billion'th generation, we look
# for the first recurring pot pattern. self._grow() will
# automatically break the loop if the recurring pattern (of pots)
# is found.
#
# Adding The Big Fucking Number, the correct sum is calculated.
initital_pots, rules = self._prepare(puzzle_input)
pots, repeated_at = self._grow(initital_pots, rules, 999)
BFN = 50 * 10 ** 9 # Big Fucking Number
return sum(k + (BFN - repeated_at) for k, v in pots.items() if v == '#')
def _grow(self, pots, rules, generations):
seen = dict()
repeated_at = 0
for g in range(1, generations + 1):
start_at = min(pots) - 5
stop_at = max(pots) + 5
span = range(start_at, stop_at)
updated = dict()
for i in span:
for rule in [''.join(pots[i + j] for j in range(-2, 3))]:
updated[i] = rules.get(rule, '.')
pots.clear()
pots.update(updated)
pattern = ''.join(pots[i] for i in span).strip('.')
if pattern in seen:
repeated_at = g
break
seen[pattern] = g
return pots, repeated_at
def _prepare(self, puzzle_input):
initial, _, *rules_data = puzzle_input.splitlines()
pots = defaultdict(lambda: '.')
pots.update({
i: v for i, v in enumerate(initial[len('initial state: '):])
})
rules = dict()
for r in rules_data:
k, v = r.split(' => ')
rules[k] = v
return pots, rules
if __name__ == '__main__':
solution = Solution()
solution.show_results()