In [1]:
import numpy as np
from itertools import product
In [2]:
def parse(fn):
acres = []
with open(fn) as f:
for line in f.readlines():
acres.append(list(line.rstrip()))
acres = np.array(acres)
return acres
In [3]:
def change(acres):
n, m = acres.shape
index = {'.': 0, '|': 1, '#': 2}
counter = np.zeros((n, m, 3))
for i in range(n):
for j in range(m):
for s, t in product([-1, 0, 1], repeat=2):
if (s**2 + t**2 != 0) and (0 <= i + s <= n-1) and (0 <= j + t <= m-1):
counter[i + s, j + t, index[acres[i, j]]] += 1
new = np.empty((n, m), dtype=object)
for i in range(n):
for j in range(m):
a = acres[i, j]
if a == '.':
if counter[i, j, 1] >= 3:
new[i, j] = '|'
else:
new[i, j] = '.'
if a == '|':
if counter[i, j, 2] >= 3:
new[i, j] = '#'
else:
new[i, j] = '|'
if a == '#':
if (counter[i, j, 1] >= 1) and (counter[i, j, 2] >= 1):
new[i, j] = '#'
else:
new[i, j] = '.'
return new
def resource_value(acres):
wooded = 0
lumber = 0
for i in range(acres.shape[0]):
for j in range(acres.shape[1]):
wooded += (acres[i, j] == '|')
lumber += (acres[i, j] == '#')
return wooded * lumber
def evolve(acres, time):
for _ in range(time):
acres = change(acres)
return acres
In [4]:
acres = parse('input_test.txt')
acres = evolve(acres, 10)
resource_value(acres)
Out[4]:
In [5]:
acres = parse('input.txt')
acres = evolve(acres, 10)
resource_value(acres)
Out[5]:
In [8]:
# Check whether some periodicity is reached soon enough that we can see it.
def get_hash(arr):
n, m = arr.shape
return ''.join(arr.reshape(1, n * m).tolist()[0])
def find_period(acres, time):
t = 0
visited = [get_hash(acres)]
res = [resource_value(acres)]
while t < time:
t += 1
acres = change(acres)
h = get_hash(acres)
if h not in visited:
visited.append(h)
res.append(resource_value(acres))
else:
i = visited.index(h)
period = t - i
return res[i + ((time - i) % period)]
In [9]:
acres = parse('input.txt')
find_period(acres, 1000000000)
Out[9]:
In [ ]: