From 61ad0cbf381434de02e4585c02ba5dd7fec5c310 Mon Sep 17 00:00:00 2001 From: Sebastian Seedorf Date: Mon, 28 Dec 2020 22:18:55 +0100 Subject: [PATCH] Day 20 (Part 2 fi-na-l-l-yyyyy) --- day20/part1-v2.py | 53 +++++++++++++++++++++ day20/part1.py | 4 +- day20/part2.py | 115 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 day20/part1-v2.py create mode 100644 day20/part2.py diff --git a/day20/part1-v2.py b/day20/part1-v2.py new file mode 100644 index 0000000..f8da7f9 --- /dev/null +++ b/day20/part1-v2.py @@ -0,0 +1,53 @@ +#!/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)) diff --git a/day20/part1.py b/day20/part1.py index 807cae7..a243b34 100644 --- a/day20/part1.py +++ b/day20/part1.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import numpy as np -l = 1000000000000 +l = -1 def calc(line): x = 0 @@ -14,7 +14,7 @@ def solve(arr, pos, s, left_keys): if pos >= s*s: return True idx = (pos // s * 2, pos % s * 2) - if l > len(left_keys): + if l != len(left_keys): print("-"*pos, pos, len(left_keys), idx) l = len(left_keys) top = (idx[0], idx[1]-1) if idx[1] > 0 else None diff --git a/day20/part2.py b/day20/part2.py new file mode 100644 index 0000000..b0b28a4 --- /dev/null +++ b/day20/part2.py @@ -0,0 +1,115 @@ +from collections import defaultdict +from functools import reduce + +import numpy as np +from scipy.signal import convolve + +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 edge_to_bin(edge): + edge = np.packbits(edge) + return edge[0] * 4 + edge[1] // 64 + + +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 = edge_to_bin(view[0]) + borders[edge].add(num) + + +for line in lines: + if line.startswith("Tile"): + num = int(line[5:-1]) + tile = np.zeros((10, 10), dtype=np.int8) + lnr = 0 + elif line == "": + add_tile(num, tile) + else: + a = np.array([(0 if x == '.' else 1) for x in line], dtype=np.int8) + tile[lnr] = a + lnr += 1 +add_tile(num, tile) + + +# find top left corner +edges = defaultdict(int) +corner = None +for key, val in borders.items(): + if len(val) == 1: + for item in val: + edges[item] += 1 +for key, val in edges.items(): + if val == 4: + corner = key + break + +# rotate top left corner +corner_tile = tiles[corner] +joints = [] +for x in range(4): + edge = edge_to_bin(corner_tile[0]) + corner_tile = np.rot90(corner_tile) + if len(borders[edge]) == 2: + joints.append(edge) + if len(joints) == 2: + break +corner_tile = np.rot90(corner_tile) + +# prepare plane +plane = np.zeros(((10-1)*12+1, (10-1)*12+1), dtype=np.int8) +plane[:10, :10] = corner_tile +used_tiles = {corner} + +# orientate and add tiles to plane +for idx in range(1, len(tiles)): + x, y = (idx % 12) * (10-1), (idx // 12) * (10-1) + next_tile_top = None if y == 0 else borders[edge_to_bin(plane[y, x:x+10])] + next_tile_left = None if x == 0 else borders[edge_to_bin(plane[y:y+10, x].T)] + if next_tile_top is None: + next_tile = next_tile_left + elif next_tile_left is None: + next_tile = next_tile_top + else: + next_tile = next_tile_left.intersection(next_tile_top) + next_tile = next_tile.difference(used_tiles).pop() + used_tiles.add(next_tile) + tile = tiles[next_tile] + for transpose, rotate in rotations: + view = np.rot90(tile.T if transpose else tile, rotate) + if y != 0 and not np.all(np.equal(plane[y, x:x+10], view[0])): + continue + if x != 0 and not np.all(np.equal(plane[y:y+10, x], view[:, 0])): + continue + plane[y:y+10, x:x+10] = view + break + +# remove all edges +plane = np.delete(plane, list(range(0, plane.shape[0], 10-1)), axis=0) +plane = np.delete(plane, list(range(0, plane.shape[1], 10-1)), axis=1) + +# kernel + + # +# ## ## ### + # # # # # # + +kernel = np.array([ + [0,0,0,0,0 ,0,0,0,0,0 ,0,0,0,0,0 ,0,0,0,1,0], + [1,0,0,0,0 ,1,1,0,0,0 ,0,1,1,0,0 ,0,0,1,1,1], + [0,1,0,0,1 ,0,0,1,0,0 ,1,0,0,1,0 ,0,1,0,0,0] +]) +count = np.sum(kernel) + +for transpose, rotate in rotations: + view = np.rot90(plane.T if transpose else plane, rotate) + neighbors = convolve(view, kernel, mode='valid') + if np.max(neighbors) == count: + print(len(np.where(view == 1)[0]) - len(np.where(neighbors == count)[0]) * count) +