2021-12-13

Created on Monday, December 13, 2021.

Day 13 - Folding like a pro

Right, I've missed about 5 days in a row due to log4j so the explanations are going to be shorter.

We've got a series of fold along instructions. At that point what we're going to have to do is take all the marked dots that are beyond the x or y foldline, and duplicate them below the line.

We're going to use a set of coordinates to indicate each of the (x,y) coords.

When we fold, we'll go through each coordinate and if it's beynd the fold, we create a new coordinate at the equivalent new location. If we hold all the coords in a set (because order doesn't matter), then it will automatically deduplicate the coordinates.

Make sense? Let's describe that with code

## Import ipytest and get it setup for use in Python Notebook
import pytest
import ipytest
ipytest.autoconfig()
from collections import namedtuple
Coord = namedtuple('Coord', ['x', 'y'])

def foldAt(axis, value, coords):
    newcoords = set()
    for coord in coords:
        x = coord.x
        y = coord.y
        if axis == "x" and x > value:
            x = value-(x-value)
        if axis == "y" and y > value:
            y = value-(y-value)
        newcoords.add(Coord(x,y))
    return newcoords

def render(coords):
    maxy = max(coords, key=lambda a: a.y).y
    maxx = max(coords, key=lambda a: a.x).x
    s=""
    for y in range(maxy+1):
        for x in range(maxx+1):
            if Coord(x,y) in coords: s+="#"
            else: s+="."
        s+="\n"
    print(s)

# Map a coordinate based on a fold line
coords = {Coord(6,10), Coord(6,12), Coord(6,0)}
assert foldAt("y", 7, coords) == {Coord(6,2), Coord(6,4), Coord(6,0) }
test_coords = {Coord(6,10), Coord(0,14), Coord(9,10), Coord(0,3), Coord(10,4), Coord(4,11), Coord(6,0), Coord(6,12), Coord(4,1), Coord(0,13), Coord(10,12), Coord(3,4), Coord(3,0), Coord(8,4), Coord(1,10), Coord(2,14), Coord(8,10), Coord(9,0)}
render(test_coords)

newtest_coords = foldAt("y", 7, test_coords)
render(newtest_coords)
assert len(newtest_coords) == 17

newtest_coords = foldAt("x", 5, newtest_coords)
render(newtest_coords)
assert len(newtest_coords) == 16

...#..#..#. ....#...... ........... #.......... ...#....#.# ........... ........... ........... ........... ........... .#....#.##. ....#...... ......#...# #.......... #.#........

#.##..#..#. #...#...... ......#...# #...#...... .#.#..#.###

##### #...# #...# #...# #####

Ok, let's try that on test data, remembering that in this case, we only want to apply the first fold instruction

(We're going to need to parse the instructions anyway I suspect)

test_lines = """6,10
0,14
9,10
0,3
10,4
4,11
6,0
6,12
4,1
0,13
10,12
3,4
3,0
8,4
1,10
2,14
8,10
9,0

fold along y=7
fold along x=5""".split("\n")

def parse(lines):
    coords = set()
    instructions = []
    i = 0
    while lines[i] != "":
        coords.add(Coord(*[int(n) for n in lines[i].split(",")]))
        i+=1
    i+=1
    while i < len(lines):
        axis, num = lines[i].split("=")
        instructions.append((axis[-1], int(num)))
        i+=1
    return coords, instructions
    
coords, instructions = parse(test_lines)
assert coords == test_coords
assert [("y", 7), ("x", 5)] == instructions

assert 17 == len(foldAt(instructions[0][0], instructions[0][1], coords))

Ok, that works, lets try on prod data

lines = [line.strip() for line in open("day13.txt").readlines()]
coords, instructions = parse(lines)
instruction = instructions[0]
print(len(foldAt(instruction[0], instruction[1], coords)))

653

Part 2 Render the Code

Somewhat as expected, do all the folds and then render

lines = [line.strip() for line in open("day13.txt").readlines()]
coords, instructions = parse(lines)
for instruction in instructions:
    coords = foldAt(instruction[0], instruction[1], coords)
render(coords)

#....#..#.###..####.###..###..###..#..# #....#.#..#..#.#....#..#.#..#.#..#.#.#. #....##...#..#.###..###..#..#.#..#.##.. #....#.#..###..#....#..#.###..###..#.#. #....#.#..#.#..#....#..#.#....#.#..#.#. ####.#..#.#..#.####.###..#....#..#.#..#

Next

2021-12-14

Previous

2021-12-12