| # flake8: noqa | |||||
| import re | |||||
| import collections | import collections | ||||
| import functools | |||||
| import itertools | import itertools | ||||
| import sys | |||||
| import math | import math | ||||
| from functools import reduce | |||||
| import re | |||||
| import sys | |||||
| def render(grid): | def render(grid): | ||||
| return '\n'.join( | |||||
| '\n'.join(''.join([n[1:-1] for n in ln]) | |||||
| for ln in zip(*[grid[y, x].splitlines()[1:-1] for x in range(size)])) | |||||
| for y in range(size) | |||||
| ) | |||||
| lines = [] | |||||
| for y in range(size): | |||||
| groups = [tiles[grid[y, x]].splitlines()[1:-1] for x in range(size)] | |||||
| for lns in zip(*groups): | |||||
| lines.append(''.join(ln[1:-1] for ln in lns)) | |||||
| return '\n'.join(lines) | |||||
| def get_borders(content): | def get_borders(content): | ||||
| a, *_, b = content.splitlines() | a, *_, b = content.splitlines() | ||||
| def variants(string): | def variants(string): | ||||
| alts = [noop, flipH], [noop, flipV], [noop, transpose] | alts = [noop, flipH], [noop, flipV], [noop, transpose] | ||||
| for ops in itertools.product(*alts): | for ops in itertools.product(*alts): | ||||
| yield reduce(lambda s, f: f(s), ops, string) | |||||
| yield functools.reduce(lambda s, f: f(s), ops, string) | |||||
| def UD(A, B): | def UD(A, B): | ||||
| return out | return out | ||||
| def reconcile(A, B, condition): | |||||
| tiles[A], tiles[B] = next( | |||||
| (X, Y) | |||||
| for X, Y in itertools.product(variants(tiles[A]), variants(tiles[B])) | |||||
| if condition(X, Y) | |||||
| ) | |||||
| text = sys.stdin.read().strip() | text = sys.stdin.read().strip() | ||||
| tiles = {} | tiles = {} | ||||
| borders = {} | borders = {} | ||||
| print(math.prod(corners)) | print(math.prod(corners)) | ||||
| gids = {} | |||||
| for y in range(size): | |||||
| for x in range(size): | |||||
| if (y, x) == (0, 0): | |||||
| gids[y, x] = corners[0] | |||||
| gids[1, 0], gids[0, 1] = adj[gids[0, 0]] | |||||
| gids[1, 1], = adj[gids[1, 0]] & adj[gids[0, 1]] - {gids[0, 0]} | |||||
| for x in range(2, size): | |||||
| gids[0, x], = adj[gids[0, x - 1]] - {gids[0, x - 2], gids[1, x - 1]} | |||||
| gids[1, x], = adj[gids[0, x]] & adj[gids[1, x - 1]] - {gids[0, x - 1]} | |||||
| for y in range(2, size): | |||||
| gids[y, 0], = adj[gids[y - 1, 0]] - {gids[y - 2, 0], gids[y - 1, 1]} | |||||
| for x in range(1, size): | |||||
| gids[y, x], = adj[gids[y, x - 1]] & adj[gids[y - 1, x]] - {gids[y - 1, x - 1]} | |||||
| grid = {(y, x): tiles[gids[y, x]] for x in range(size) for y in range(size)} | |||||
| grid[0, 0] = flipV(grid[0, 0]) | |||||
| for y in range(size): | |||||
| for x in range(size): | |||||
| if (x, y) != (0, 0): | |||||
| grid[y, x], = ( | |||||
| pic for pic in variants(grid[y, x]) | |||||
| if ((y - 1, x) not in grid or UD(grid[y - 1, x], pic)) | |||||
| and ((y, x - 1) not in grid or LR(grid[y, x - 1], pic)) | |||||
| ) | |||||
| A = min(corners) | |||||
| B, C = adj.pop(A) | |||||
| grid = {(y, x): None for x in range(size) for y in range(size)} | |||||
| grid[0, 0] = A | |||||
| grid[0, 1] = B | |||||
| grid[1, 0] = C | |||||
| reconcile(A, B, condition=LR) | |||||
| reconcile(A, C, condition=UD) | |||||
| seen = {A, B, C} | |||||
| for z in range(2, 2 * size - 1): | |||||
| # determine new pieces from intersection between 2 neighbors | |||||
| for y, x in {(y, z - y) for y in range(1, z)}.intersection(grid): | |||||
| U, L = (y - 1, x), (y, x - 1) | |||||
| grid[y, x], = adj[grid[U]] & adj[grid[L]] - seen | |||||
| reconcile(grid[L], grid[y, x], condition=LR) | |||||
| seen.add(grid[y, x]) | |||||
| # determine new piece from only one alternative left | |||||
| for y, x in {(0, z), (z, 0)}.intersection(grid): | |||||
| opts = {(y - 1, x): UD, (y, x - 1): LR} | |||||
| P, fn = next(p for p in opts.items() if p[0] in grid) | |||||
| grid[y, x], = adj[grid[P]] - seen | |||||
| reconcile(grid[P], grid[y, x], condition=fn) | |||||
| seen.add(grid[y, x]) | |||||
| monster = ''' | monster = ''' | ||||
| ..................#. | ..................#. |