From 259eb2430874f945c0508d0f68e67185d2d67452 Mon Sep 17 00:00:00 2001 From: Sebastian Seedorf Date: Tue, 29 Dec 2020 15:42:56 +0100 Subject: [PATCH] Day 20 (works for any square puzzle size with 10x10 tiles) --- day20/part1-v2.py | 53 ------------------------ day20/part1.py | 101 ++++++++++++++++------------------------------ day20/part2.py | 6 +-- 3 files changed, 37 insertions(+), 123 deletions(-) delete mode 100644 day20/part1-v2.py diff --git a/day20/part1-v2.py b/day20/part1-v2.py deleted file mode 100644 index f8da7f9..0000000 --- a/day20/part1-v2.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/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 a243b34..f8da7f9 100644 --- a/day20/part1.py +++ b/day20/part1.py @@ -1,86 +1,53 @@ #!/usr/bin/env python3 + +from collections import defaultdict +from functools import reduce + import numpy as np -l = -1 - -def calc(line): - x = 0 - for elem in line: - x = x*2 + elem - return x - - -def solve(arr, pos, s, left_keys): - global l - if pos >= s*s: - return True - idx = (pos // s * 2, pos % s * 2) - 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 - bottom = (idx[0], idx[1]+1) if idx[1] < s else None - left = (idx[0]-1, idx[1]) if idx[0] > 0 else None - right = (idx[0]+1, idx[1]) if idx[0] < s else None - for key in left_keys: - new_keys = left_keys.copy() - new_keys.discard(key) - for transpose, rotate in ([(False, 0)] if pos == 0 else rotations): - view = np.rot90(tiles[key].T if transpose else tiles[key], rotate) - if (top is None or arr[top] == -1 or arr[top] == calc(view[0])) and \ - (bottom is None or arr[bottom] == -1 or arr[bottom] == calc(view[-1])) and \ - (left is None or arr[left] == -1 or arr[left] == calc(view[:, 0])) and \ - (right is None or arr[right] == -1 or arr[right] == calc(view[:, -1])): - arr[idx] = key - if right is not None: - arr[right] = calc(view[:, -1]) - if bottom is not None: - arr[bottom] = calc(view[-1]) - #print("B", arr) - #print("bef", pos) - if pos % s == 0: - p = pos // s + 1 - p = p if p != s else p+s-1 - else: - p = pos + s - 1 - p = p if p <= s*s-1 else (p-s*s+3)*s-1 - #print("change", p) - if solve(arr, p, s, new_keys): - return True - arr[idx] = -1 - if right is not None: - arr[right] = -1 - if bottom is not None: - arr[bottom] = -1 - return False 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) + -num = None -tile = None -lnr = None for line in lines: if line.startswith("Tile"): num = int(line[5:-1]) - tile = np.zeros((10, 10), dtype=np.int8) + tile = np.zeros((10, 10), dtype=np.int16) lnr = 0 elif line == "": - tiles[num] = tile + add_tile(num, tile) else: - a = np.array([(0 if x == '.' else 1) for x in line], dtype=np.int8) + a = np.array([(0 if x == '.' else 1) for x in line], dtype=np.int16) tile[lnr] = a lnr += 1 -tiles[num] = tile +add_tile(num, tile) -size = int(np.sqrt(len(tiles))) -positioning = -np.ones((size*2-1, size*2-1), dtype=np.int64) -print(positioning.shape) +# 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 -if solve(positioning, 0, size, set(tiles.keys())): - print(positioning) - print(positioning[0, 0]*positioning[-1, 0]*positioning[0, -1]*positioning[-1, -1]) -else: - print("fail") +print(reduce(lambda a, b: a*b, (key for key, val in edges.items() if val == 4), 1)) diff --git a/day20/part2.py b/day20/part2.py index b0b28a4..9209430 100644 --- a/day20/part2.py +++ b/day20/part2.py @@ -36,7 +36,7 @@ for line in lines: tile[lnr] = a lnr += 1 add_tile(num, tile) - +WIDTH = int(np.sqrt(len(tiles))) # find top left corner edges = defaultdict(int) @@ -63,13 +63,13 @@ for x in range(4): corner_tile = np.rot90(corner_tile) # prepare plane -plane = np.zeros(((10-1)*12+1, (10-1)*12+1), dtype=np.int8) +plane = np.zeros(((10-1)*WIDTH+1, (10-1)*WIDTH+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) + x, y = (idx % WIDTH) * (10-1), (idx // WIDTH) * (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: