| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- #!/usr/bin/env python3
- import sys
- import time
- OPEN, TREE, LUMB = range(3)
- trans = {'.': OPEN, '|': TREE, '#': LUMB}
- initial = []
- for line in sys.stdin:
- w = len(line) + 1
- initial += [OPEN, *(trans[c] for c in line.rstrip()), OPEN]
- pad = [OPEN] * w
- initial = pad + initial + pad
- h = len(initial) // w
- def simulate(minutes):
- prev = list(initial)
- grid = [0] * len(prev)
- for minute in range(minutes):
- for y in range(1, h - 1):
- for x in range(1, w - 1):
- i = y * w + x
- cell = prev[i]
- counts = [0, 0, 0]
- for d in (-w - 1, -w, -w + 1, -1, 1, w - 1, w, w + 1):
- counts[prev[i + d]] += 1
- if cell == OPEN and counts[TREE] >= 3:
- cell = TREE
- elif cell == TREE and counts[LUMB] >= 3:
- cell = LUMB
- elif cell == LUMB and (not counts[LUMB] or not counts[TREE]):
- cell = OPEN
- grid[i] = cell
- counts = [0, 0, 0]
- for x in grid:
- counts[x] += 1
- yield counts[TREE] * counts[LUMB], hash(tuple(grid))
- prev, grid = grid, prev
- # part 1
- for val, ident in simulate(10):
- last = val
- print(last)
- # part 2
- def find_pattern(n):
- seen = []
- for minute, result in enumerate(simulate(n)):
- for i in range(len(seen) - 1, -1, -1):
- if seen[i] == result:
- return minute, tuple(zip(*seen[i:]))[0]
- seen.append(result)
- n = 1000000000
- minute, pattern = find_pattern(n)
- print(pattern[(n - minute - 1) % len(pattern)])
|