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