|
|
|
|
|
|
|
|
import math |
|
|
import math |
|
|
from functools import reduce |
|
|
from functools import reduce |
|
|
|
|
|
|
|
|
import toolkit |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def apply(cell): |
|
|
|
|
|
string, *fns = cell |
|
|
|
|
|
for fn in fns: |
|
|
|
|
|
if fn is not None: |
|
|
|
|
|
string = fn(string) |
|
|
|
|
|
return string |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def apply2(string, fns): |
|
|
|
|
|
for fn in fns: |
|
|
|
|
|
if fn is not None: |
|
|
|
|
|
string = fn(string) |
|
|
|
|
|
return string |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def render(grid): |
|
|
def render(grid): |
|
|
return '\n'.join( |
|
|
return '\n'.join( |
|
|
'\n'.join(''.join([n[1:-1] |
|
|
'\n'.join(''.join([n[1:-1] |
|
|
for n in ln]) |
|
|
for n in ln]) |
|
|
for ln in zip(*[apply(grid[y, x]).splitlines()[1:-1] for x in range(size)])) |
|
|
|
|
|
|
|
|
for ln in zip(*[grid[y, x].splitlines()[1:-1] for x in range(size)])) |
|
|
for y in range(size) |
|
|
for y in range(size) |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return [a, b, c, d, a[::-1], b[::-1], c[::-1], d[::-1]] |
|
|
return [a, b, c, d, a[::-1], b[::-1], c[::-1], d[::-1]] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def transpose(string): |
|
|
|
|
|
return '\n'.join(''.join(ln) for ln in zip(*string.splitlines())) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def flipV(string): |
|
|
def flipV(string): |
|
|
return '\n'.join(ln for ln in string.splitlines()[::-1]) |
|
|
return '\n'.join(ln for ln in string.splitlines()[::-1]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def rot90(n): |
|
|
def rot90(n): |
|
|
def inner(string): |
|
|
def inner(string): |
|
|
return toolkit.render({k * 1j ** n: v for k, v in toolkit.read_image(string)[0].items()}) |
|
|
|
|
|
|
|
|
return flipH(transpose(string)) |
|
|
return inner |
|
|
return inner |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def variants(string): |
|
|
def variants(string): |
|
|
alts = [noop, flipH], [noop, flipV], [noop, rot90(1), rot90(2), rot90(3)] |
|
|
alts = [noop, flipH], [noop, flipV], [noop, rot90(1), rot90(2), rot90(3)] |
|
|
for ops in itertools.product(*alts): |
|
|
for ops in itertools.product(*alts): |
|
|
yield reduce(lambda s, f: f(s), ops, string), ops |
|
|
|
|
|
|
|
|
yield reduce(lambda s, f: f(s), ops, string) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def search_in(source, target): |
|
|
def search_in(source, target): |
|
|
|
|
|
|
|
|
gids[y][x], = adj[gids[y][x - 1]] & adj[gids[y - 1][x]] - {gids[y - 1][x - 1]} |
|
|
gids[y][x], = adj[gids[y][x - 1]] & adj[gids[y - 1][x]] - {gids[y - 1][x - 1]} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
options = list(itertools.product([None, flipH], [None, flipV], [None] + [rot90(n) for n in range(3)])) |
|
|
|
|
|
|
|
|
grid = {(y, x): tiles[gids[y][x]] for x in range(size) for y in range(size)} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
grid = {(y, x): (tiles[gids[y][x]],) for x in range(size) for y in range(size)} |
|
|
|
|
|
grid[0, 0] = (flipV(grid[0, 0][0]),) |
|
|
|
|
|
|
|
|
def UD(A, B): |
|
|
|
|
|
return A.splitlines()[-1] == B.splitlines()[0] |
|
|
|
|
|
|
|
|
|
|
|
def LR(A, B): |
|
|
|
|
|
return UD(rot90(1)(A), rot90(1)(B)) |
|
|
|
|
|
|
|
|
for x in range(1, size): |
|
|
|
|
|
goal = [ln[-1] for ln in apply(grid[0, x - 1]).splitlines()] |
|
|
|
|
|
for chain in options: |
|
|
|
|
|
if goal == [ln[0] for ln in apply(grid[0, x] + chain).splitlines()]: |
|
|
|
|
|
grid[0, x] += chain |
|
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
for y in range(1, size): |
|
|
|
|
|
|
|
|
for y in range(size): |
|
|
for x in range(size): |
|
|
for x in range(size): |
|
|
goal = apply(grid[y - 1, x]).splitlines()[-1] |
|
|
|
|
|
for chain in options: |
|
|
|
|
|
if goal == apply(grid[y, x] + chain).splitlines()[0]: |
|
|
|
|
|
grid[y, x] += chain |
|
|
|
|
|
break |
|
|
|
|
|
|
|
|
if (y, x) == (0, 0): |
|
|
|
|
|
grid[y, x] = flipV(grid[y, x]) |
|
|
|
|
|
elif y == 0: |
|
|
|
|
|
grid[y, x] = next(pic for pic in variants(grid[0, x]) if LR(grid[y, x - 1], pic)) |
|
|
|
|
|
else: |
|
|
|
|
|
grid[y, x] = next(pic for pic in variants(grid[y, x]) if UD(grid[y - 1, x], pic)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
monster = ''' |
|
|
monster = ''' |
|
|
|
|
|
|
|
|
.#..#..#..#..#..#... |
|
|
.#..#..#..#..#..#... |
|
|
'''[1:-1] |
|
|
'''[1:-1] |
|
|
src = render(grid) |
|
|
src = render(grid) |
|
|
found = max([search_in(pic, monster) for pic, _ in variants(src)], key=len) |
|
|
|
|
|
|
|
|
found = max([search_in(pic, monster) for pic in variants(src)], key=len) |
|
|
print(src.count('#') - len(found) * monster.count('#')) |
|
|
print(src.count('#') - len(found) * monster.count('#')) |