Roderic Day vor 4 Jahren
Ursprung
Commit
ba4cf21abc
1 geänderte Dateien mit 48 neuen und 37 gelöschten Zeilen
  1. +48
    -37
      y2020/p20.py

+ 48
- 37
y2020/p20.py Datei anzeigen

import itertools import itertools
import sys import sys
import math import math
from functools import reduce


import toolkit import toolkit




def apply(cell): def apply(cell):
key, *fns = cell
string = tiles[key]
string, *fns = cell
for fn in fns: for fn in fns:
if fn is not None: if fn is not None:
string = fn(string) string = fn(string)
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(cell).splitlines()[1:-1] for cell in row]))
for row in grid
for ln in zip(*[apply(grid[y, x]).splitlines()[1:-1] for x in range(size)]))
for y in range(size)
) )




return inner return inner




def noop(string):
return string


def variants(string):
alts = [noop, flipH], [noop, flipV], [noop, rot90(1), rot90(2), rot90(3)]
for ops in itertools.product(*alts):
yield reduce(lambda s, f: f(s), ops, string), ops


def search_in(source, target):
source_lns = source.splitlines()
target_lns = target.splitlines()
h, w = len(target_lns), len(target_lns[0])
out = []
for y in range(len(source_lns)):
for x in range(len(source_lns[0])):
window = '\n'.join(ln[x:x + w] for ln in source_lns[y:y + h])
if re.fullmatch(target, window):
out.append((x, y))
return out


text = sys.stdin.read().strip() text = sys.stdin.read().strip()
tiles = {} tiles = {}
borders = {} borders = {}
tid = int(title.split()[1]) tid = int(title.split()[1])
tiles[tid] = content tiles[tid] = content
borders[tid] = get_borders(content) borders[tid] = get_borders(content)


size = int(len(borders) ** 0.5)

size = int(len(tiles) ** 0.5)


adj = collections.defaultdict(set) adj = collections.defaultdict(set)
for (aid, A), (bid, B) in itertools.combinations(borders.items(), 2): for (aid, A), (bid, B) in itertools.combinations(borders.items(), 2):
if set(A) & set(B): if set(A) & set(B):
adj[aid].add(bid) adj[aid].add(bid)
adj[bid].add(aid) adj[bid].add(aid)

corn = [v for v, ks in adj.items() if len(ks) == 2] corn = [v for v, ks in adj.items() if len(ks) == 2]
print(math.prod(corn))



gids = [[None for _ in range(size)] for _ in range(size)] gids = [[None for _ in range(size)] for _ in range(size)]


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]}




grid = [[(gids[y][x],) for x in range(size)] for y in range(size)]
grid[0][0] += (flipV,)

options = list(itertools.product([None, flipH], [None, flipV], [None] + [rot90(n) for n in range(3)])) 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[0, 0] = (flipV(grid[0, 0][0]),)


for x in range(1, size): for x in range(1, size):
goal = [ln[-1] for ln in apply(grid[0][x - 1]).splitlines()]
goal = [ln[-1] for ln in apply(grid[0, x - 1]).splitlines()]
for chain in options: for chain in options:
if goal == [ln[0] for ln in apply(grid[0][x] + chain).splitlines()]:
grid[0][x] += chain
if goal == [ln[0] for ln in apply(grid[0, x] + chain).splitlines()]:
grid[0, x] += chain
break break


for y in range(1, size): for y in range(1, size):
for x in range(size): for x in range(size):
goal = apply(grid[y - 1][x]).splitlines()[-1]
goal = apply(grid[y - 1, x]).splitlines()[-1]
for chain in options: for chain in options:
if goal == apply(grid[y][x] + chain).splitlines()[0]:
grid[y][x] += chain
if goal == apply(grid[y, x] + chain).splitlines()[0]:
grid[y, x] += chain
break break




monster = ''' #
# ## ## ###
# # # # # # '''
kuk, W, H = toolkit.read_image(monster)
goal = re.compile(toolkit.render(kuk).replace('\n', '').replace(' ', '.'))

cnt = 0
for chain in options:
grody = apply2(render(grid), chain)
grok = [list(line) for line in grody.splitlines()]
for y in range(len(grok) - H):
for x in range(len(grok[0]) - W):
sample = ''.join(''.join(grok[y + dy][x + dx] for dx in range(W)) for dy in range(H))
cnt += bool(goal.fullmatch(sample))
if cnt:
break

print(grody)
print(grody.count('#') - cnt * monster.count('#'))
monster = '''
..................#.
#....##....##....###
.#..#..#..#..#..#...
'''[1:-1]
src = render(grid)
found = max([search_in(pic, monster) for pic, _ in variants(src)], key=len)
print(src.count('#') - len(found) * monster.count('#'))

Laden…
Abbrechen
Speichern