95 lines
2.9 KiB
Python
95 lines
2.9 KiB
Python
from tools.aoc import AOCDay
|
|
from tools.coordinate import Coordinate
|
|
from tools.grid import Grid, GridTransformation
|
|
from typing import Any
|
|
|
|
|
|
FLIPS = [
|
|
GridTransformation.ROTATE_RIGHT,
|
|
GridTransformation.ROTATE_RIGHT,
|
|
GridTransformation.ROTATE_RIGHT,
|
|
GridTransformation.ROTATE_RIGHT,
|
|
GridTransformation.FLIP_HORIZONTALLY,
|
|
GridTransformation.ROTATE_RIGHT,
|
|
GridTransformation.ROTATE_RIGHT,
|
|
GridTransformation.ROTATE_RIGHT,
|
|
]
|
|
|
|
|
|
def init_grid() -> Grid:
|
|
grid = Grid()
|
|
grid.set(Coordinate(1, 0))
|
|
grid.set(Coordinate(2, 1))
|
|
grid.set(Coordinate(0, 2))
|
|
grid.set(Coordinate(1, 2))
|
|
grid.set(Coordinate(2, 2))
|
|
return grid
|
|
|
|
|
|
class Day(AOCDay):
|
|
inputs = [
|
|
[
|
|
(12, "input21_test"),
|
|
(176, "input21")
|
|
],
|
|
[
|
|
(2368161, "input21")
|
|
]
|
|
]
|
|
|
|
def load_replacement_grids(self) -> dict:
|
|
ret = {}
|
|
for line in self.getInput():
|
|
rep, grid_string = line.split(" => ")
|
|
ret[rep] = Grid.from_str(grid_string, true_char='#')
|
|
rep_grid_size = len(rep.split("/")[0]) + 1
|
|
ret[rep].minX, ret[rep].maxX, ret[rep].minY, ret[rep].maxY = 0, rep_grid_size, 0, rep_grid_size
|
|
|
|
return ret
|
|
|
|
def interact(self, interact_count: int) -> int:
|
|
grid = Grid.from_str('.#./..#/###')
|
|
grid_size = 3
|
|
replacements = self.load_replacement_grids()
|
|
|
|
for i in range(2 if self._current_test_file.endswith('test') else interact_count):
|
|
new_grid = Grid()
|
|
block_size = 3
|
|
replace_size = 4
|
|
if grid_size % 2 == 0:
|
|
block_size = 2
|
|
replace_size = 3
|
|
|
|
for x in range(0, grid_size, block_size):
|
|
for y in range(0, grid_size, block_size):
|
|
sub_grid = grid.sub_grid(x, y, x + block_size - 1, y + block_size - 1)
|
|
sub_grid.minX, sub_grid.minY, sub_grid.maxX, sub_grid.maxY = 0, 0, block_size - 1, block_size - 1
|
|
for f in FLIPS:
|
|
sub_grid.transform(f)
|
|
sub_grid.maxX, sub_grid.maxY = block_size - 1 + sub_grid.minX, block_size - 1 + sub_grid.minY
|
|
if str(sub_grid) in replacements:
|
|
new_grid.update(
|
|
x // block_size * replace_size,
|
|
y // block_size * replace_size,
|
|
replacements[str(sub_grid)]
|
|
)
|
|
break
|
|
else:
|
|
raise ValueError("No sub_grid matches found.")
|
|
|
|
grid = new_grid
|
|
grid_size = grid_size // block_size * replace_size
|
|
|
|
return grid.getOnCount()
|
|
|
|
def part1(self) -> Any:
|
|
return self.interact(5)
|
|
|
|
def part2(self) -> Any:
|
|
return self.interact(18)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
day = Day(2017, 21)
|
|
day.run(verbose=True)
|