Puzzle #8

 14th July 2023 at 2:09pm

First part

2023-07-11-Tuesday

Interesting stuff! I have been having the puzzle on my mind since yesterday, and today I managed to squeeze a few programming thinking minutes into the later part of the day.

HEIGHT = 6
WIDTH = 50

SCREEN = [['.' for _ in range(WIDTH)]
          for _ in range(HEIGHT)]


def display_screen(screen: list[str]):
    [print(line) for line in screen]
    print()


def produce_new_lines(
        old: list[str],
        a: int,
        b: int
        ) -> list[str]:
    """produces `b` new lines with `a`
    columns of `#` and the remaining
    columns with the previous screen content"""
    return [['#' for _ in range(a)] + old[i][a:] for i in range(b)]


# a: width; b: height
def handle_rect(
        old: list[str],
        a: int,
        b: int
        ) -> list[str]:
    return produce_new_lines(old, a, b) + old[b:]


def handle_x_rotate(
        old: list[str],
        x: int,
        amount: int
        ) -> list[str]:
    old_deque = deque(old[x])
    old_deque.rotate(amount)
    return old[:x] + [list(old_deque)] + old[x + 1:]


def handle_y_rotate(
        old: list[str],
        y: int,
        amount: int
        ) -> list[str]:
    transpose = list(zip(*old))
    return zip(*handle_x_rotate(transpose, y, amount))

All that's missing now is a parser, but I haven't given it much thought yet. Maybe tomorrow it will be finished.


2023-07-14-Friday

Alas, it is not yet finished. I did some further work in the parsing, but I wasn't as rigorous with it. I really don't know what would be best practices for a functional parser. These have been very busy days, so I'm trying to make very small steps every time I find a few minutes I could dispense to programming.

I was having some miscellaneous issues that I managed to fix in some ten minutes; the code was not so bad (but it definitely feels long)

HEIGHT = 6
WIDTH = 50

SCREEN = [['.' for _ in range(WIDTH)]
          for _ in range(HEIGHT)]


def display_screen(screen: list[str]):
    [print(line) for line in screen]
    print()


def produce_new_lines(
        old: list[str],
        a: int,
        b: int
        ) -> list[str]:
    """produces `b` new lines with `a`
    columns of `#` and the remaining
    columns with the previous screen content"""
    return [['#' for _ in range(a)] + list(old[i][a:]) for i in range(b)]


# a: width; b: height
def handle_rect(
        old: list[str],
        a: int,
        b: int
        ) -> list[str]:
    return produce_new_lines(old, a, b) + old[b:]


def handle_x_rotate(
        old: list[str],
        x: int,
        amount: int
        ) -> list[str]:
    old_deque = deque(old[x])
    old_deque.rotate(amount)
    return old[:x] + [list(old_deque)] + old[x + 1:]


def handle_y_rotate(
        old: list[str],
        y: int,
        amount: int
        ) -> list[str]:
    transpose = list(zip(*old))
    return list(zip(*handle_x_rotate(transpose, y, amount)))


def iterate_through_lines(
        screen: list[str],
        lines: list[str]
        ) -> list[str]:
    if not lines:
        return screen
    else:
        instr = lines[0].split()
        if instr[0] == 'rect':
            screen = (handle_rect(
                      screen,
                      *list(map(int, (instr[1].split('x'))))))
        # instruction is 'rotate'
        else:
            f = handle_x_rotate if instr[1] == 'row' else \
                    handle_y_rotate
            screen = (f(screen,
                        *list(map(int, re.findall(
                            r'(\d+) by (\d+)', lines[0])[0]))))
    return iterate_through_lines(screen, lines[1:])


with open('input') as file_input:
    INPUT = file_input.read().splitlines()

print(reduce(lambda x, y: x + y.count('#'),
             iterate_through_lines(SCREEN, INPUT),
             0))

Part 2

For Part 2, I'd do something more rigorous if I had the time; instead, I just zoomed my terminal out, enough to see the image form itself.