feat: solve day 20 part 2!!!
This commit is contained in:
parent
ec25382f66
commit
46e6fa1852
103
20/main.py
103
20/main.py
@ -9,6 +9,8 @@ class Tile:
|
|||||||
right: str
|
right: str
|
||||||
bottom: str
|
bottom: str
|
||||||
|
|
||||||
|
inner: list[str]
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "Tile"
|
return "Tile"
|
||||||
|
|
||||||
@ -22,7 +24,10 @@ def parse_tile(tile_data: str) -> tuple[int, Tile]:
|
|||||||
right_edge = "".join(line[-1] for line in lines[1:])
|
right_edge = "".join(line[-1] for line in lines[1:])
|
||||||
left_edge = "".join(line[0] for line in lines[1:])
|
left_edge = "".join(line[0] for line in lines[1:])
|
||||||
bottom_edge = lines[-1]
|
bottom_edge = lines[-1]
|
||||||
return id, Tile(top_edge, left_edge, right_edge, bottom_edge)
|
|
||||||
|
raw_inner = list(line[1:-1] for line in lines[2:-1])
|
||||||
|
|
||||||
|
return id, Tile(top_edge, left_edge, right_edge, bottom_edge, raw_inner)
|
||||||
|
|
||||||
def parse_input(filename: str) -> TilesData:
|
def parse_input(filename: str) -> TilesData:
|
||||||
tiles = {}
|
tiles = {}
|
||||||
@ -33,12 +38,20 @@ def parse_input(filename: str) -> TilesData:
|
|||||||
tiles[id] = tile
|
tiles[id] = tile
|
||||||
return tiles
|
return tiles
|
||||||
|
|
||||||
|
def flip_image(image: list[str]):
|
||||||
|
return image[::-1]
|
||||||
|
|
||||||
|
def rotate_image(image: list[str]):
|
||||||
|
return ["".join(col[::-1]) for col in zip(*image)]
|
||||||
|
|
||||||
def rotate_tile(tile) -> Tile:
|
def rotate_tile(tile) -> Tile:
|
||||||
return Tile(
|
return Tile(
|
||||||
top = tile.left[::-1],
|
top = tile.left[::-1],
|
||||||
right = tile.top,
|
right = tile.top,
|
||||||
bottom = tile.right[::-1],
|
bottom = tile.right[::-1],
|
||||||
left = tile.bottom
|
left = tile.bottom,
|
||||||
|
|
||||||
|
inner=rotate_image(tile.inner)
|
||||||
)
|
)
|
||||||
|
|
||||||
def flip_tile(tile) -> Tile:
|
def flip_tile(tile) -> Tile:
|
||||||
@ -46,7 +59,9 @@ def flip_tile(tile) -> Tile:
|
|||||||
top = tile.bottom,
|
top = tile.bottom,
|
||||||
right = tile.right[::-1],
|
right = tile.right[::-1],
|
||||||
bottom = tile.top,
|
bottom = tile.top,
|
||||||
left = tile.left[::-1]
|
left = tile.left[::-1],
|
||||||
|
|
||||||
|
inner=tile.inner[::-1]
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_grid_size(tiles: TilesData) -> int:
|
def get_grid_size(tiles: TilesData) -> int:
|
||||||
@ -69,6 +84,25 @@ def get_tile_variants(tile: Tile) -> Iterator[Tile]:
|
|||||||
for t in get_rotated_tiles(tile):
|
for t in get_rotated_tiles(tile):
|
||||||
yield t
|
yield t
|
||||||
|
|
||||||
|
def get_image_variants(image: list[str]) -> Iterator[list[str]]:
|
||||||
|
yield image
|
||||||
|
image = rotate_image(image)
|
||||||
|
yield image
|
||||||
|
image = rotate_image(image)
|
||||||
|
yield image
|
||||||
|
image = rotate_image(image)
|
||||||
|
yield image
|
||||||
|
image = rotate_image(image)
|
||||||
|
|
||||||
|
image = flip_image(image)
|
||||||
|
yield image
|
||||||
|
image = rotate_image(image)
|
||||||
|
yield image
|
||||||
|
image = rotate_image(image)
|
||||||
|
yield image
|
||||||
|
image = rotate_image(image)
|
||||||
|
yield image
|
||||||
|
|
||||||
def is_tile_possible(grid: TileGrid, x: int, y: int, tile: Tile) -> bool:
|
def is_tile_possible(grid: TileGrid, x: int, y: int, tile: Tile) -> bool:
|
||||||
if x > 0:
|
if x > 0:
|
||||||
other_tile = grid[y][x-1]
|
other_tile = grid[y][x-1]
|
||||||
@ -133,8 +167,8 @@ def multiply_corners(grid: TileGrid) -> int:
|
|||||||
assert bottom_right
|
assert bottom_right
|
||||||
return top_left[0] * top_right[0] * bottom_right[0] * bottom_left[0]
|
return top_left[0] * top_right[0] * bottom_right[0] * bottom_left[0]
|
||||||
|
|
||||||
def part1(tiles: TilesData) -> int:
|
def solve_grid(tiles_data: TilesData) -> TileGrid:
|
||||||
width = get_grid_size(tiles)
|
width = get_grid_size(tiles_data)
|
||||||
|
|
||||||
grid: TileGrid = []
|
grid: TileGrid = []
|
||||||
for _ in range(width):
|
for _ in range(width):
|
||||||
@ -142,8 +176,63 @@ def part1(tiles: TilesData) -> int:
|
|||||||
|
|
||||||
solve(tiles, grid)
|
solve(tiles, grid)
|
||||||
|
|
||||||
return multiply_corners(grid)
|
return grid
|
||||||
|
|
||||||
|
def get_full_image(grid: TileGrid) -> list[str]:
|
||||||
|
rows = []
|
||||||
|
for y in range(len(grid)):
|
||||||
|
row = []
|
||||||
|
for x in range(len(grid[0])):
|
||||||
|
cell = grid[y][x]
|
||||||
|
assert cell
|
||||||
|
inner = cell[1].inner
|
||||||
|
if x == 0:
|
||||||
|
row = inner.copy()
|
||||||
|
else:
|
||||||
|
for i in range(len(inner)):
|
||||||
|
row[i] += inner[i]
|
||||||
|
rows.extend(row)
|
||||||
|
|
||||||
|
return rows
|
||||||
|
|
||||||
|
def is_sea_monster(image: list[str], sea_monster: list[str], x: int, y: int) -> bool:
|
||||||
|
for oy in range(len(sea_monster)):
|
||||||
|
for ox in range(len(sea_monster[0])):
|
||||||
|
if sea_monster[oy][ox] == "#" and image[y+oy][x+ox] != "#":
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def count_symbol(image: list[str], symbol: str) -> int:
|
||||||
|
return sum(sum(c == symbol for c in row) for row in image)
|
||||||
|
|
||||||
|
def count_sea_monsters(image: list[str], sea_monster: list[str]) -> int:
|
||||||
|
monsters = 0
|
||||||
|
|
||||||
|
for y in range(len(image)-len(sea_monster)+1):
|
||||||
|
for x in range(len(image[0])-len(sea_monster[0])+1):
|
||||||
|
if is_sea_monster(image, sea_monster, x, y):
|
||||||
|
monsters += 1
|
||||||
|
|
||||||
|
return monsters
|
||||||
|
|
||||||
|
def part2(grid: TileGrid) -> int:
|
||||||
|
image = get_full_image(grid)
|
||||||
|
sea_monster = [
|
||||||
|
" # ",
|
||||||
|
"# ## ## ###",
|
||||||
|
" # # # # # # "
|
||||||
|
]
|
||||||
|
|
||||||
|
max_monsters = 0
|
||||||
|
for variant in get_image_variants(sea_monster):
|
||||||
|
monsters = count_sea_monsters(image, variant)
|
||||||
|
max_monsters = max(max_monsters, monsters)
|
||||||
|
|
||||||
|
return count_symbol(image, "#") - count_symbol(sea_monster, "#") * max_monsters
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
tiles = parse_input("input.txt")
|
tiles = parse_input("input.txt")
|
||||||
print("part1: ", part1(tiles))
|
grid = solve_grid(tiles)
|
||||||
|
|
||||||
|
print("part1: ", multiply_corners(grid))
|
||||||
|
print("part2: ", part2(grid))
|
||||||
|
Loading…
Reference in New Issue
Block a user