2021-12-20 - Trench Map
(original .ipynb)
Day 20 puzzle input is the input parameter for an image enhancement algorithm and a small 5x5 image to be enhanced (mine is here). Part 1 involves implementing the defined enhancement algorithm, applying it two times and finding the number of # pixels. Part 2 involves doing the same but applying the algorithm 50 times.
test_input_str = """..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..##
#..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###
.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#.
.#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#.....
.#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#..
...####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.....
..##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#
#..#.
#....
##..#
..#..
..###"""
puzzle_input_str = open("puzzle_input/day20.txt").read()
from advent import grid_animated_render_frame, grid_animated_combine
def parse_image(image_str):
image = []
for line in image_str.split("\n"):
image.append([c for c in line])
return image
def parse_input(input_str):
algo_str, image_str = input_str.split("\n\n")
return algo_str.replace("\n", ""), parse_image(image_str)
def dump_image(image):
for line in image:
print("".join(line))
def grow_image(image, pad):
if "#" in image[0]:
# image.insert(0, ["."]*len(image[0]))
image.insert(0, [pad]*len(image[0]))
if "#" in image[-1]:
# image.append(["."]*len(image[-1]))
image.append([pad]*len(image[-1]))
leftmost_chars = [row[0] for row in image]
if "#" in leftmost_chars:
for r in range(len(image)):
image[r].insert(0, pad)
rightmost_chars = [row[-1] for row in image]
if "#" in rightmost_chars:
for r in range(len(image)):
image[r].append(pad)
def get_pixel(image, r, c, pad):
if r < 0 or r >= len(image):
return pad
if c < 0 or c >= len(image[r]):
return pad
# print(len(image), "rows")
# print(len(image[0]), "cols")
# print("accessing row", r, "col", c)
# dump_image(image)
return image[r][c]
def get_enhancement_index(image, r, c, pad):
blob = []
for dr in [-1, 0, 1]:
for dc in [-1, 0, 1]:
px = get_pixel(image, r+dr, c+dc, pad)
#print(r+dr, c+dc, px)
blob.append("1" if px == "#" else "0")
return int("".join(blob), 2)
def enhance(image, algo_str, pad):
grow_image(image, pad)
new_image = []
for r in range(len(image)):
row = []
for c in range(len(image[r])):
idx = get_enhancement_index(image, r, c, pad)
row.append(algo_str[idx])
new_image.append(row)
return new_image
def count_lit(image):
count = 0
# this is baby stuff, need to write it better
for row in image:
for col in row:
if col == "#":
count += 1
return count
# def grid_animated_render_frame(grid, palette, cell_size=10, bg_color="white"):
# def grid_animated_combine(images, filename, duration=100, loop=0, show=False):
palette = {
".": "white",
"#": "black"
}
def create_frame(image):
img_size = 300
# image centered in it ... sorta
r_pad = (img_size - len(image)) // 2
c_pad = (img_size - len(image[0])) // 2
new_image = []
for r in range(img_size):
new_image.append(["."] * img_size)
for r, row in enumerate(image):
for c, col in enumerate(row):
new_image[r_pad+r][c_pad+c] = col
return grid_animated_render_frame(new_image, palette, cell_size=1)
def part_one(input_str, iterations=2, filename=None):
algo_str, image = parse_input(input_str)
step = 0
frames = []
while step < iterations:
pad = "." if step % 2 == 0 else algo_str[0]
image = enhance(image, algo_str, pad)
if filename:
frames.append(create_frame(image))
step += 1
if filename:
grid_animated_combine(frames, filename, duration=250, show=True)
return count_lit(image)
assert 35 == part_one(test_input_str)
print("part one:", part_one(puzzle_input_str, filename="day21-p1.gif"))
part one: 5498
def part_two(input_str, filename=None):
# lol
return part_one(input_str, 50, filename)
assert 3351 == part_two(test_input_str)
print("part two:", part_two(puzzle_input_str, filename="day21-p2.gif"))
part two: 16014