Working on 2017/21 part 1

This commit is contained in:
FrederikBaerentsen 2024-11-28 18:47:06 +01:00
parent 99982f4fb9
commit 0549ff028e
4 changed files with 280 additions and 1 deletions

116
2017/21/21.md Normal file
View File

@ -0,0 +1,116 @@
## \-\-- Day 21: Fractal Art \-\--
You find a program trying to generate some art. It uses a strange
process that involves [repeatedly
enhancing]{title="This technique is also often used on TV."} the detail
of an image through a set of rules.
The image consists of a two-dimensional square grid of pixels that are
either on (`#`) or off (`.`). The program always begins with this
pattern:
.#.
..#
###
Because the pattern is both `3` pixels wide and `3` pixels tall, it is
said to have a *size* of `3`.
Then, the program repeats the following process:
- If the size is evenly divisible by `2`, break the pixels up into
`2x2` squares, and convert each `2x2` square into a `3x3` square by
following the corresponding *enhancement rule*.
- Otherwise, the size is evenly divisible by `3`; break the pixels up
into `3x3` squares, and convert each `3x3` square into a `4x4`
square by following the corresponding *enhancement rule*.
Because each square of pixels is replaced by a larger one, the image
gains pixels and so its *size* increases.
The artist\'s book of enhancement rules is nearby (your puzzle input);
however, it seems to be missing rules. The artist explains that
sometimes, one must *rotate* or *flip* the input pattern to find a
match. (Never rotate or flip the output pattern, though.) Each pattern
is written concisely: rows are listed as single units, ordered top-down,
and separated by slashes. For example, the following rules correspond to
the adjacent patterns:
../.# = ..
.#
.#.
.#./..#/### = ..#
###
#..#
#..#/..../#..#/.##. = ....
#..#
.##.
When searching for a rule to use, rotate and flip the pattern as
necessary. For example, all of the following patterns match the same
rule:
.#. .#. #.. ###
..# #.. #.# ..#
### ### ##. .#.
Suppose the book contained the following two rules:
../.# => ##./#../...
.#./..#/### => #..#/..../..../#..#
As before, the program begins with this pattern:
.#.
..#
###
The size of the grid (`3`) is not divisible by `2`, but it is divisible
by `3`. It divides evenly into a single square; the square matches the
second rule, which produces:
#..#
....
....
#..#
The size of this enhanced grid (`4`) is evenly divisible by `2`, so that
rule is used. It divides evenly into four squares:
#.|.#
..|..
--+--
..|..
#.|.#
Each of these squares matches the same rule (`../.# => ##./#../...`),
three of which require some flipping and rotation to line up with the
rule. The output for the rule is the same in all four cases:
##.|##.
#..|#..
...|...
---+---
##.|##.
#..|#..
...|...
Finally, the squares are joined into a new grid:
##.##.
#..#..
......
##.##.
#..#..
......
Thus, after `2` iterations, the grid contains `12` pixels that are *on*.
*How many pixels stay on* after `5` iterations?
To begin, [get your puzzle input](21/input).
Answer:

145
2017/21/solution.py Normal file
View File

@ -0,0 +1,145 @@
#!/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 = 'test'
part = 1
#########################################
# #
# Part 1 #
# #
#########################################
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):
size = len(grid)
block_size = 0
if size % 2 == 0:
block_size = 2
elif size % 3 == 0:
block_size = 3
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 findInst(grid,instructions):
found = False
new_grid = []
grid = grid
while not found:
try:
new_grid = instructions[grid2line(grid)]
found = True
except:
grid = rotate90(grid)
return new_grid
def transform_grid(input_grid):
result = []
for half in [input_grid[:2], input_grid[2:]]:
for i in range(3): # Each subgrid has 3 rows
# Merge the rows from the two subgrids in the current half
row = ''.join([''.join(subgrid[i]) for subgrid in half])
result.append(row)
return result
if part == 1:
instructions = toSet(input_f,r"^(.*) => (.*)$")
print(instructions)
blocks = []
mixed_grid = [[]]
for i in range(0,5):
size = len(grid)
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)
#print(len(blocks))
#print(blocks)
print(blocks)
input()
mixed_grid = []
for i in range(0,len(blocks)):
x = line2grid(findInst(blocks[i],instructions))
mixed_grid.append(x)
grid = transform_grid(mixed_grid)
#nprint(grid)
#input()
else:
print('Something is wrong with the grid size of ', size)
#input()
#########################################
# #
# Part 2 #
# #
#########################################
if part == 2:
exit()

Binary file not shown.

20
fred.py
View File

@ -1,4 +1,22 @@
import re
import re,sys
def toGrid(input,parser=None):
grid = []
if parser:
with open(input) as file:
for line in file:
grid.append(list2int(line.rstrip()))
else:
with open(input) as file:
for line in file:
grid.append(line.rstrip())
return grid
def nprint(grid):
for idx,i in enumerate(grid):
for jdx,j in enumerate(i):
print(grid[idx][jdx],end='')
print()
def list2int(x):
return list(map(int, x))