Day 20 (works for any square puzzle size with 10x10 tiles)
This commit is contained in:
@@ -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))
|
|
||||||
101
day20/part1.py
101
day20/part1.py
@@ -1,86 +1,53 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
import numpy as np
|
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"))
|
lines = (x.strip() for x in open("input.txt"))
|
||||||
rotations = [(t, r) for t in (True, False) for r in range(4)]
|
rotations = [(t, r) for t in (True, False) for r in range(4)]
|
||||||
tiles = {}
|
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:
|
for line in lines:
|
||||||
if line.startswith("Tile"):
|
if line.startswith("Tile"):
|
||||||
num = int(line[5:-1])
|
num = int(line[5:-1])
|
||||||
tile = np.zeros((10, 10), dtype=np.int8)
|
tile = np.zeros((10, 10), dtype=np.int16)
|
||||||
lnr = 0
|
lnr = 0
|
||||||
elif line == "":
|
elif line == "":
|
||||||
tiles[num] = tile
|
add_tile(num, tile)
|
||||||
else:
|
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
|
tile[lnr] = a
|
||||||
lnr += 1
|
lnr += 1
|
||||||
tiles[num] = tile
|
add_tile(num, tile)
|
||||||
|
|
||||||
size = int(np.sqrt(len(tiles)))
|
# every border matches only once
|
||||||
positioning = -np.ones((size*2-1, size*2-1), dtype=np.int64)
|
print("sum joints", sum(1 for key, val in borders.items() if len(val) > 1))
|
||||||
print(positioning.shape)
|
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(reduce(lambda a, b: a*b, (key for key, val in edges.items() if val == 4), 1))
|
||||||
print(positioning)
|
|
||||||
print(positioning[0, 0]*positioning[-1, 0]*positioning[0, -1]*positioning[-1, -1])
|
|
||||||
else:
|
|
||||||
print("fail")
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ for line in lines:
|
|||||||
tile[lnr] = a
|
tile[lnr] = a
|
||||||
lnr += 1
|
lnr += 1
|
||||||
add_tile(num, tile)
|
add_tile(num, tile)
|
||||||
|
WIDTH = int(np.sqrt(len(tiles)))
|
||||||
|
|
||||||
# find top left corner
|
# find top left corner
|
||||||
edges = defaultdict(int)
|
edges = defaultdict(int)
|
||||||
@@ -63,13 +63,13 @@ for x in range(4):
|
|||||||
corner_tile = np.rot90(corner_tile)
|
corner_tile = np.rot90(corner_tile)
|
||||||
|
|
||||||
# prepare plane
|
# 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
|
plane[:10, :10] = corner_tile
|
||||||
used_tiles = {corner}
|
used_tiles = {corner}
|
||||||
|
|
||||||
# orientate and add tiles to plane
|
# orientate and add tiles to plane
|
||||||
for idx in range(1, len(tiles)):
|
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_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)]
|
next_tile_left = None if x == 0 else borders[edge_to_bin(plane[y:y+10, x].T)]
|
||||||
if next_tile_top is None:
|
if next_tile_top is None:
|
||||||
|
|||||||
Reference in New Issue
Block a user