# --- Day 8: Two-Factor Authentication --- # You come across a door implementing what you can only assume is an # implementation of two-factor authentication after a long game of # requirements telephone. # To get past the door, you first swipe a keycard (no problem; there was one on # a nearby desk). Then, it displays a code on a little screen, and you type # that code on a keypad. Then, presumably, the door unlocks. # Unfortunately, the screen has been smashed. After a few minutes, you've taken # everything apart and figured out how it works. Now you just have to work out # what the screen would have displayed. # The magnetic strip on the card you swiped encodes a series of instructions # for the screen; these instructions are your puzzle input. The screen is 50 # pixels wide and 6 pixels tall, all of which start off, and is capable of # three somewhat peculiar operations: # rect AxB turns on all of the pixels in a rectangle at the top-left of the # screen which is A wide and B tall. # rotate row y=A by B shifts all of the pixels in row A (0 is the top row) # right by B pixels. Pixels that would fall off the right end appear at the # left end of the row. # rotate column x=A by B shifts all of the pixels in column A (0 is the # left column) down by B pixels. Pixels that would fall off the bottom appear # at the top of the column. # For example, here is a simple sequence on a smaller screen: # rect 3x2 creates a small rectangle in the top-left corner: # ###.... # ###.... # ....... # rotate column x=1 by 1 rotates the second column down by one pixel: # #.#.... # ###.... # .#..... # rotate row y=0 by 4 rotates the top row right by four pixels: # ....#.# # ###.... # .#..... # rotate column x=1 by 1 again rotates the second column down by one pixel, # causing the bottom pixel to wrap back to the top: # .#..#.# # #.#.... # .#..... # As you can see, this display technology is extremely powerful, and will soon # dominate the tiny-code-displaying-screen market. That's what the # advertisement on the back of the display tries to convince you, anyway. # There seems to be an intermediate check of the voltage used by the display: # after you swipe your card, if the screen did work, how many pixels should be # lit? import numpy as np import numpy.typing as npt with open("files/P8.txt") as f: instructions = [line for line in f.read().strip().split("\n")] def rect(instruction: str, grid: npt.NDArray[int]) -> npt.NDArray[int]: _, row = instruction.split("x") _, col = _.split() grid[: int(row), : int(col)] = 1 def rotate_column( instruction: str, grid: npt.NDArray[int] ) -> npt.NDArray[int]: _, cols = instruction.split("=") x, _, steps = cols.split() new_col = np.roll(grid[:, int(x) : int(x) + 1], int(steps), axis=0) grid[:, int(x) : int(x) + 1] = new_col def rotate_row(instruction: str, grid: npt.NDArray[int]) -> npt.NDArray[int]: _, rows = instruction.split("=") y, _, steps = rows.split() new_row = np.roll(grid[int(y) : int(y) + 1, :], int(steps), axis=1) grid[int(y) : int(y) + 1, :] = new_row # dimensions given by the problem init_grid = np.zeros((6, 50), dtype=int) def part_1() -> None: for instruction in instructions: if instruction.startswith("rect"): rect(instruction, init_grid) elif instruction.startswith("rotate row"): rotate_row(instruction, init_grid) elif instruction.startswith("rotate column"): rotate_column(instruction, init_grid) lit = np.sum(init_grid) print(f"There should be {lit} pixels lit") # --- Part Two --- # You notice that the screen is only capable of displaying capital letters; in # the font it uses, each letter is 5 pixels wide and 6 tall. # After you swipe your card, what code is the screen trying to display? def display(grid: npt.NDArray[int]) -> None: print( "\n".join("".join("X" if one else " " for one in row) for row in grid) ) def part_2() -> None: print("The code is the following:\n") display(init_grid) if __name__ == "__main__": part_1() part_2()