AdventOfCode/2017/21/solution.py

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)