204 lines
5.1 KiB
Python
204 lines
5.1 KiB
Python
#!/bin/python3
|
|
import sys,re, math
|
|
from copy import deepcopy
|
|
import numpy as np
|
|
from pprint import pprint
|
|
sys.path.insert(0, '../../')
|
|
from fred import list2int, toGrid, nprint,get_re
|
|
|
|
input_f = 'input'
|
|
|
|
part = 1
|
|
#########################################
|
|
# #
|
|
# Part 1+2 #
|
|
# #
|
|
#########################################
|
|
|
|
instructions = {}
|
|
|
|
grid = [
|
|
['.','#','.'],
|
|
['.','.','#'],
|
|
['#','#','#']
|
|
]
|
|
|
|
def toSet(input,regex):
|
|
set = {}
|
|
with open(input) as file:
|
|
for line in file:
|
|
r = get_re(regex, line.rstrip())
|
|
set[r.group(1).replace('/','')] = r.group(2).replace('/','')
|
|
return set
|
|
|
|
def need2split(grid):
|
|
if len(grid) > 3:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def grid2line(grid):
|
|
line = ''
|
|
for i in grid:
|
|
line += ''.join(i)
|
|
return line
|
|
|
|
def line2grid(line):
|
|
grid = []
|
|
size = int(math.sqrt(len(line)))
|
|
for i in range(size):
|
|
grid.append(list(line[i*size:size*(1+i)]))
|
|
return grid
|
|
|
|
def rotate90(grid):
|
|
rotatedGrid = np.array(deepcopy(grid))
|
|
return np.rot90(rotatedGrid)
|
|
|
|
def splitGrid(grid):
|
|
#print('Splitting')
|
|
#nprint(grid)
|
|
size = len(grid)
|
|
block_size = 0
|
|
if size % 2 == 0:
|
|
block_size = 2
|
|
else:
|
|
block_size = 3
|
|
|
|
#print('Size:',size,' Block_size:',block_size)
|
|
#else:
|
|
# print('Grind is wrong at splitGrid()')
|
|
|
|
blocks = []
|
|
|
|
for i in range(0, size, block_size):
|
|
for j in range(0, size, block_size):
|
|
block = [row[j:j+block_size] for row in grid[i:i+block_size]]
|
|
#print(block)
|
|
for bdx,b in enumerate(block):
|
|
block[bdx] = list(b)
|
|
#print(block)
|
|
#input()
|
|
blocks.append(block)
|
|
return blocks
|
|
|
|
def get_all_transformations(grid):
|
|
grid = np.array(grid)
|
|
transformations = set()
|
|
|
|
for k in range(4):
|
|
rotated = np.rot90(grid, k)
|
|
# Add original rotation
|
|
if tuple(map(tuple, rotated)) not in transformations:
|
|
transformations.add(tuple(map(tuple, rotated)))
|
|
yield rotated
|
|
|
|
# Add horizontal flip of rotation
|
|
h_flip = np.flipud(rotated)
|
|
if tuple(map(tuple, h_flip)) not in transformations:
|
|
transformations.add(tuple(map(tuple, h_flip)))
|
|
yield h_flip
|
|
|
|
# Add vertical flip of rotation
|
|
v_flip = np.fliplr(rotated)
|
|
if tuple(map(tuple, v_flip)) not in transformations:
|
|
transformations.add(tuple(map(tuple, v_flip)))
|
|
yield v_flip
|
|
|
|
|
|
def findInst(grid,instructions):
|
|
found = False
|
|
new_grid = []
|
|
grid = grid
|
|
while not found:
|
|
|
|
for transformed_grid in get_all_transformations(grid):
|
|
|
|
#print(grid2line(transformed_grid))
|
|
#input()
|
|
|
|
try:
|
|
new_grid = instructions[grid2line(transformed_grid)]
|
|
|
|
found = True
|
|
break
|
|
except:
|
|
continue
|
|
|
|
return new_grid
|
|
|
|
def transform_grid(input_grid):
|
|
# Determine the dimensions of the grid
|
|
num_subgrids = len(input_grid)
|
|
subgrid_rows = len(input_grid[0]) # Rows in each subgrid
|
|
subgrid_cols = len(input_grid[0][0]) # Columns in each subgrid
|
|
|
|
# Calculate the number of subgrids per row and column
|
|
subgrids_per_row = int(num_subgrids ** 0.5)
|
|
|
|
# Initialize the result
|
|
result = []
|
|
|
|
# Process each row of subgrids
|
|
for subgrid_row_idx in range(subgrids_per_row):
|
|
# Merge corresponding rows from subgrids in the current "row of subgrids"
|
|
for row_idx in range(subgrid_rows):
|
|
row = ''.join(
|
|
''.join(input_grid[subgrid_row_idx * subgrids_per_row + col_idx][row_idx])
|
|
for col_idx in range(subgrids_per_row)
|
|
)
|
|
result.append(row)
|
|
|
|
return result
|
|
rr = 0
|
|
if part == 1:
|
|
rr = 5
|
|
if part == 2:
|
|
rr = 18
|
|
instructions = toSet(input_f,r"^(.*) => (.*)$")
|
|
|
|
#print(instructions)
|
|
blocks = []
|
|
mixed_grid = [[]]
|
|
for i in range(0,rr):
|
|
size = len(grid)
|
|
print('i:',i)
|
|
#nprint(grid)
|
|
#print()
|
|
if size % 3 == 0 or size % 2 == 0:
|
|
if not need2split(grid):
|
|
new_grid = findInst(grid,instructions)
|
|
grid = line2grid(new_grid)
|
|
#print(grid)
|
|
else:
|
|
blocks = splitGrid(grid)
|
|
#print(blocks)
|
|
|
|
#pprint(blocks)
|
|
|
|
#print(len(blocks))
|
|
#print(blocks)
|
|
#print(blocks)
|
|
#input()
|
|
mixed_grid = []
|
|
|
|
|
|
for i in range(0,len(blocks)):
|
|
#print(findInst(blocks[i],instructions))
|
|
x = line2grid(findInst(blocks[i],instructions))
|
|
#print(x)
|
|
#input()
|
|
mixed_grid.append(x)
|
|
|
|
#print(mixed_grid)
|
|
grid = transform_grid(mixed_grid)
|
|
#nprint(grid)
|
|
#input()
|
|
|
|
else:
|
|
print('Something is wrong with the grid size of ', size)
|
|
#input()
|
|
count = 0
|
|
for i in grid:
|
|
count += i.count('#')
|
|
print(count)
|