Last active
February 15, 2021 04:43
-
-
Save sciyoshi/4a297cd965baad369f5f544029a10dbc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import functools | |
import operator | |
import itertools | |
import networkx | |
import numpy as np | |
tiles = {} | |
for tiledata in open("inputs/day20").read().strip().split("\n\n"): | |
a, *tilelines = tiledata.splitlines() | |
num = int(a.strip(":").split()[1]) | |
tiles[num] = np.array([[c == "#" for c in l] for l in tilelines], dtype=np.uint8) | |
def nptobin(s): | |
return int("".join([str(k) for k in s]), 2) | |
def get_borders(n): | |
return [nptobin(n[0]), nptobin(n[:, -1]), nptobin(n[-1]), nptobin(n[:, 0])] | |
def get_flips(tile): | |
res = tile | |
for f in [True, False]: | |
for i in range(4): | |
yield res | |
res = np.rot90(res) | |
res = np.flip(tile, 1) | |
borders = {} | |
for n, tile in tiles.items(): | |
borders[n] = set.union(*[set(get_borders(fl)) for fl in get_flips(tile)]) | |
grph = networkx.Graph() | |
for i, j in itertools.combinations(borders, 2): | |
if len(borders[i] & borders[j]) == 2: | |
grph.add_edge(i, j) | |
corners = [n for n in grph if len(grph[n]) == 2] | |
print("part1:", functools.reduce(operator.mul, corners)) | |
def ext(pt): | |
used = set(tile for tile, _ in grd.values()) | |
tile, img = grd[pt] | |
border = get_borders(img) | |
for nb in grph[tile]: | |
if nb not in used: | |
for fl in get_flips(tiles[nb]): | |
if get_borders(fl)[0] == border[2]: | |
grd[(pt[0] + 1, pt[1])] = (nb, fl) | |
if get_borders(fl)[3] == border[1]: | |
grd[(pt[0], pt[1] + 1)] = (nb, fl) | |
for fl in get_flips(tiles[corners[0]]): | |
grd = {} | |
grd[(0, 0)] = (corners[0], fl) | |
ext((0, 0)) | |
if len(grd) == 3: | |
break | |
for i in range(12): | |
for j in range(12): | |
ext((i, j)) | |
image = np.concatenate([np.concatenate([grd[i, j][1][1:-1, 1:-1] for j in range(12)], axis=1) for i in range(12)], axis=0) | |
monster_str = ( | |
" # \n" | |
"# ## ## ###\n" | |
" # # # # # # ".splitlines() | |
) | |
monster = np.array([[c == "#" for c in l] for l in monster_str], dtype=np.uint8) | |
for image in get_flips(image): | |
count = 0 | |
for i in range(image.shape[0] - monster.shape[0] + 1): | |
for j in range(image.shape[1] - monster.shape[1] + 1): | |
check = image[i : i + monster.shape[0], j : j + monster.shape[1]] | |
if (check & monster == monster).all(): | |
count += 1 | |
if count: | |
break | |
print("part 2:", int(np.sum(image) - count * np.sum(monster))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment