aoc2017/day21.py

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)