mid-kid
4 years ago
3 changed files with 1875 additions and 0 deletions
@ -0,0 +1,145 @@ |
|||||
|
#!/usr/bin/env python3 |
||||
|
|
||||
|
from sys import argv |
||||
|
from math import sqrt |
||||
|
|
||||
|
tiles = {} |
||||
|
for tile in map(lambda x: x.splitlines(), open(argv[1]).read().strip().split("\n\n")): |
||||
|
tiles[int(tile[0][5:-1])] = "".join(tile[1:]) |
||||
|
|
||||
|
size = int(sqrt(len(tiles))) |
||||
|
tsize = int(sqrt(len(next(iter(tiles.values()))))) |
||||
|
|
||||
|
sides = {} |
||||
|
sides_rev = {} |
||||
|
for tile in tiles: |
||||
|
data = tiles[tile] |
||||
|
up = data[0:tsize] |
||||
|
down = data[tsize ** 2 - tsize:tsize ** 2] |
||||
|
left = "" |
||||
|
right = "" |
||||
|
for x in range(tsize): |
||||
|
left += data[tsize * x] |
||||
|
right += data[tsize * x + tsize - 1] |
||||
|
up = up[::-1] |
||||
|
right = right[::-1] |
||||
|
|
||||
|
sides[tile] = [ |
||||
|
up, left, down, right, |
||||
|
up[::-1], left[::-1], down[::-1], right[::-1] |
||||
|
] |
||||
|
for i, side in enumerate(sides[tile]): |
||||
|
if side not in sides_rev: |
||||
|
sides_rev[side] = [] |
||||
|
sides_rev[side].append((tile, i)) |
||||
|
|
||||
|
tiles_noconn = {} |
||||
|
for side in sides_rev: |
||||
|
if len(sides_rev[side]) == 1: |
||||
|
tile, orien = sides_rev[side][0] |
||||
|
if tile not in tiles_noconn: |
||||
|
tiles_noconn[tile] = [] |
||||
|
tiles_noconn[tile].append(orien) |
||||
|
tiles_corner = [i for i, noconn in tiles_noconn.items() if len(noconn) == 4] |
||||
|
print(tiles_corner[0] * tiles_corner[1] * tiles_corner[2] * tiles_corner[3]) |
||||
|
|
||||
|
# Figure out the orientation of the top-left corner tile we pick |
||||
|
orien = tiles_noconn[tiles_corner[0]] |
||||
|
if 3 in orien and 0 in orien: |
||||
|
orien = 3 |
||||
|
else: |
||||
|
orien = min(orien) |
||||
|
corner = (tiles_corner[0], orien) |
||||
|
|
||||
|
def get_orien(base, add): |
||||
|
if base & 4: |
||||
|
add = 4 - add |
||||
|
return ((base + add) & 3) | (base & 4) |
||||
|
|
||||
|
# Create a connection graph |
||||
|
conn = {} |
||||
|
for side in sides_rev.values(): |
||||
|
if len(side) != 2: |
||||
|
continue |
||||
|
conn[side[0]] = side[1] |
||||
|
conn[side[1]] = side[0] |
||||
|
|
||||
|
# Put the grid together, starting from the top-left corner, going right then down |
||||
|
grid = [] |
||||
|
for y in range(size): |
||||
|
if y: |
||||
|
tile_top, orien_top = grid[y-1][0] |
||||
|
orien_top = get_orien(orien_top, 2) |
||||
|
tile, orien = conn[(tile_top, orien_top)] |
||||
|
orien ^= 4 |
||||
|
row = [(tile, orien)] |
||||
|
else: |
||||
|
row = [corner] |
||||
|
|
||||
|
for x in range(1, size): |
||||
|
tile_left, orien_left = row[x-1] |
||||
|
orien_left = get_orien(orien_left, 3) |
||||
|
tile, orien = conn[(tile_left, orien_left)] |
||||
|
orien = get_orien(orien, -1) |
||||
|
orien ^= 6 |
||||
|
row.append((tile, orien)) |
||||
|
|
||||
|
grid.append(row) |
||||
|
|
||||
|
def rotate(tile, orien): |
||||
|
# Flip the tile if necessary |
||||
|
if orien >= 4: |
||||
|
tile = [row[::-1] for row in tile] |
||||
|
orien = (4 - orien) % 4 |
||||
|
# Rotate the tile |
||||
|
for x in range(orien): |
||||
|
tile = [[tile[len(iy) - x - 1][y] for x, ix in enumerate(iy)] for y, iy in enumerate(tile)] |
||||
|
return tile |
||||
|
|
||||
|
# Create image |
||||
|
ssize = tsize - 2 |
||||
|
image = [[0] * size * ssize for x in range(size * ssize)] |
||||
|
for y, row in enumerate(grid): |
||||
|
y *= ssize |
||||
|
for x, (tile, orien) in enumerate(row): |
||||
|
x *= ssize |
||||
|
|
||||
|
# Convert tile data into grid, strip the edges |
||||
|
tile = [tiles[tile][x + 1:x + tsize - 1] for x in range(tsize, tsize ** 2 - tsize, tsize)] |
||||
|
tile = rotate(tile, orien) |
||||
|
|
||||
|
# Store into image |
||||
|
for iy, irow in enumerate(tile): |
||||
|
for ix, c in enumerate(irow): |
||||
|
image[y + iy][x + ix] = c |
||||
|
|
||||
|
# Find monsters |
||||
|
monster = """ |
||||
|
# |
||||
|
# ## ## ### |
||||
|
# # # # # # |
||||
|
""" |
||||
|
monster = [(y,x) for y, line in enumerate(monster[1:-1].split("\n")) for x, char in enumerate(line) if char == "#"] |
||||
|
monster_h = 3 |
||||
|
monster_w = 20 |
||||
|
|
||||
|
for orien in range(8): |
||||
|
cur_image = rotate(image, orien) |
||||
|
count = 0 |
||||
|
for y in range(size * ssize - monster_h): |
||||
|
for x in range(size * ssize - monster_w): |
||||
|
for m in monster: |
||||
|
if cur_image[m[0] + y][m[1] + x] != "#": |
||||
|
break |
||||
|
else: |
||||
|
for m in monster: |
||||
|
cur_image[m[0] + y][m[1] + x] = "O" |
||||
|
count += 1 |
||||
|
if count: |
||||
|
break |
||||
|
|
||||
|
# Tally roughness |
||||
|
print(sum(1 for row in cur_image for char in row if char == "#")) |
||||
|
|
||||
|
# for row in cur_image: |
||||
|
# print("".join(row)) |
File diff suppressed because it is too large
@ -0,0 +1,2 @@ |
|||||
|
66020135789767 |
||||
|
1537 |
Loading…
Reference in new issue