#!/usr/bin/env python3 import sys import numpy as np def toBits(l): return sum(int(b=='#') * (2**i) for i,b in enumerate(l)) def allSides(tile): a,b,c,d = tile[0, : ], tile[-1, : ], tile[:, 0], tile[:, -1] e,f,g,h = tile[0, ::-1], tile[-1, ::-1], tile[::-1, 0], tile[::-1, -1] return [a,b,c,d,e,f,g,h] def comb(tile): return [tile, np.fliplr(tile), np.rot90(tile), np.rot90(np.rot90(tile)), np.rot90(np.rot90(np.rot90(tile))), np.fliplr(np.rot90(tile)), np.fliplr(np.rot90(np.rot90(tile))), np.fliplr(np.rot90(np.rot90(np.rot90(tile))))] def getRight(tile): return toBits(tile[:,-1]) def getLeft(tile): return toBits(tile[:,0]) def getBot(tile): return toBits(tile[-1,:]) def getTop(tile): return toBits(tile[0,:]) def matchRight(tile1, tile2): for t in comb(tile2): if getRight(tile1) == getLeft(t): return t def matchBot(tile1, tile2): for t in comb(tile2): if getBot(tile1) == getTop(t): return t if __name__ == '__main__': tilestrings = open(sys.argv[1]).read().split('\n\n') tiles = {} for tile in tilestrings: tid, *data = tile.split('\n') try: tid = tid.rstrip(':').split(' ')[1] except IndexError: continue grid = [[c for c in line] for line in data if len(line) >= 1] tiles[int(tid)] = np.array(grid) sides = {} for tid, tile in tiles.items(): for x in allSides(tile): bits = toBits(x) if bits not in sides: sides[bits] = [] sides[bits].append(tid) sides = {k:v for k,v in sorted(sides.items(), key=lambda i: len(i[1]))} singles = {} for bits, xs in sides.items(): if len(xs) == 1: singles[xs[0]] = [] for sid in singles.keys(): matches = [x for side in allSides(tiles[sid]) for x in sides[toBits(side)]] singles[sid] = list(dict.fromkeys(matches)) prod = 1 corner = None for sid, single in singles.items(): if len(single) < 4: prod *= sid corner = sid picture = [[None for x in range(12)] for x in range(12)] matches = list(dict.fromkeys([x for side in allSides(tiles[corner]) for x in sides[toBits(side)]])) matches.remove(corner) for t in comb(tiles[corner]): x, y = matches x, y = tiles[x], tiles[y] if matchRight(t,x) is not None and matchBot(t,y) is not None: tiles[corner] = t break if matchRight(t,y) is not None and matchBot(t,x) is not None: tiles[corner] = t break picture[0][0] = corner for i, p in enumerate(picture[0]): s = sides[getRight(tiles[p])] s.remove(p) if len(s) > 0: tiles[s[0]] = matchRight(tiles[p], tiles[s[0]]) picture[0][i+1] = s[0] for j in range(1, len(picture)): z = sides[getBot(tiles[p])] z.remove(p) if len(z) > 0: tiles[z[0]] = matchBot(tiles[p], tiles[z[0]]) picture[j][i] = z[0] p = z[0] print(picture) pic = [[None for x in range(12)] for x in range(12)] for i in range(len(picture)): for j in range(len(picture[0])): pic[i][j] = tiles[picture[i][j]] print(pic)