diff --git a/src/Year_2016/P8.py b/src/Year_2016/P8.py index de99af6..0f41041 100644 --- a/src/Year_2016/P8.py +++ b/src/Year_2016/P8.py @@ -1,53 +1,111 @@ -import numpy as np +# --- Day 8: Two-Factor Authentication --- -with open("files/test") as f: +# 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")] -print(instructions) -# grid = np.zeros((6,50), dtype=int) -init_grid = np.zeros((3, 7), dtype=int) - -# initialize grid -print(init_grid) +def rect(instruction: str, grid: npt.NDArray[int]) -> npt.NDArray[int]: + _, row = instruction.split("x") + _, col = _.split() + grid[: int(row), : int(col)] = 1 -def rect(instruction, grid): - col, row = int(instruction[5:6]), int(instruction[7:]) - # print(col,row) - grid[:row, :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 -rect(instructions[0], init_grid) - -print(init_grid) +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 -def rotate_column(instruction, grid): - x, steps = int(instruction[16:17]), int(instruction[21:]) - # print(x, steps) - new_col = np.roll(grid[:, x : x + 1], steps, axis=0) - grid[:, x : x + 1] = new_col +def part_1() -> None: + # dimensions given by the problem + init_grid = np.zeros((6, 50), dtype=int) + + 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") -rotate_column(instructions[1], init_grid) - -print(init_grid) - - -def rotate_row(instruction, grid): - y, steps = int(instruction[13:14]), int(instruction[18:]) - # print(y, steps) - new_row = np.roll(grid[y : y + 1, :], steps, axis=1) - grid[y : y + 1, :] = new_row - - -rotate_row(instructions[2], init_grid) - -print(init_grid) - -rotate_column(instructions[3], init_grid) - -print(init_grid) - -print(np.sum(init_grid)) +if __name__ == "__main__": + part_1()