#!/usr/bin/env python3 from collections import defaultdict from functools import reduce import numpy as np lines = (x.strip() for x in open("input.txt")) rotations = [(t, r) for t in (True, False) for r in range(4)] tiles = {} borders = defaultdict(set) def add_tile(num, tile): global tiles, borders tiles[num] = tile for transpose, rotate in rotations: view = np.rot90(tile.T if transpose else tile, rotate) edge = np.packbits(view[0]) edge = edge[0] * 4 + edge[1] // 64 borders[edge].add(num) for line in lines: if line.startswith("Tile"): num = int(line[5:-1]) tile = np.zeros((10, 10), dtype=np.int16) lnr = 0 elif line == "": add_tile(num, tile) else: a = np.array([(0 if x == '.' else 1) for x in line], dtype=np.int16) tile[lnr] = a lnr += 1 add_tile(num, tile) # every border matches only once print("sum joints", sum(1 for key, val in borders.items() if len(val) > 1)) print("should joints", (len(tiles)-np.sqrt(len(tiles))) * 2) print("sum outer", sum(1 for key, val in borders.items() if len(val) == 1)) print("should outer", np.sqrt(len(tiles)) * 4) print("cnt tiles", len(tiles)) print("multi matches", sum(1 for key, val in borders.items() if len(val) > 2)) # find corners edges = defaultdict(int) for key, val in borders.items(): if len(val) == 1: for item in val: edges[item] += 1 print(reduce(lambda a, b: a*b, (key for key, val in edges.items() if val == 4), 1))