# --- Day 8: Space Image Format --- # The Elves' spirits are lifted when they realize you have an opportunity to # reboot one of their Mars rovers, and so they are curious if you would spend a # brief sojourn on Mars. You land your ship near the rover. # When you reach the rover, you discover that it's already in the process of # rebooting! It's just waiting for someone to enter a BIOS password. The Elf # responsible for the rover takes a picture of the password (your puzzle input) # and sends it to you via the Digital Sending Network. # Unfortunately, images sent via the Digital Sending Network aren't encoded # with any normal encoding; instead, they're encoded in a special Space Image # Format. None of the Elves seem to remember why this is the case. They send # you the instructions to decode it. # Images are sent as a series of digits that each represent the color of a # single pixel. The digits fill each row of the image left-to-right, then move # downward to the next row, filling rows top-to-bottom until every pixel of the # image is filled. # Each image actually consists of a series of identically-sized layers that are # filled in this way. So, the first digit corresponds to the top-left pixel of # the first layer, the second digit corresponds to the pixel to the right of # that on the same layer, and so on until the last digit, which corresponds to # the bottom-right pixel of the last layer. # For example, given an image 3 pixels wide and 2 pixels tall, the image data # 123456789012 corresponds to the following image layers: # Layer 1: 123 # 456 # Layer 2: 789 # 012 # The image you received is 25 pixels wide and 6 pixels tall. # To make sure the image wasn't corrupted during transmission, the Elves would # like you to find the layer that contains the fewest 0 digits. On that layer, # what is the number of 1 digits multiplied by the number of 2 digits? from collections import Counter with open("files/P8.txt") as f: digits = [ int(digit) for line in f.read().strip().split() for digit in line ] def part_1() -> None: picture_size = 25 * 6 layers = [] for i in range(0, len(digits), picture_size): layer = Counter(digits[i : i + picture_size]) layers.append(layer) fewest_zeros = min(layer[0] for layer in layers) for layer in layers: if layer[0] == fewest_zeros: print(f"The result is {layer[1] * layer[2]}") # --- Part Two --- # Now you're ready to decode the image. The image is rendered by stacking the # layers and aligning the pixels with the same positions in each layer. The # digits indicate the color of the corresponding pixel: 0 is black, 1 is white, # and 2 is transparent. # The layers are rendered with the first layer in front and the last layer in # back. So, if a given position has a transparent pixel in the first and second # layers, a black pixel in the third layer, and a white pixel in the fourth # layer, the final image would have a black pixel at that position. # For example, given an image 2 pixels wide and 2 pixels tall, the image data # 0222112222120000 corresponds to the following image layers: # Layer 1: 02 # 22 # Layer 2: 11 # 22 # Layer 3: 22 # 12 # Layer 4: 00 # 00 # Then, the full image can be found by determining the top visible pixel in # each position: # The top-left pixel is black because the top layer is 0. # The top-right pixel is white because the top layer is 2 (transparent), # but the second layer is 1. # The bottom-left pixel is white because the top two layers are 2, but the # third layer is 1. # The bottom-right pixel is black because the only visible pixel in that # position is 0 (from layer 4). # So, the final image looks like this: # 01 # 10 # What message is produced after decoding your image? def part_2() -> None: picture_size = 25 * 6 layers = [] for i in range(0, len(digits), picture_size): layer = digits[i : i + picture_size] layers.append(layer) full_image = [] for pixel in range(picture_size): for layer in layers: if layer[pixel] == 2: continue full_image.append(layer[pixel]) # only grab the first non-transparent pixel break for idx, pixel in enumerate(full_image): # only black (0) and white (1) pixels are in the full image if pixel == 0: print(" ", end="") elif pixel == 1: print("X", end="") # wrap around image's width (25 pixels) if (idx + 1) % 25 == 0: print() if __name__ == "__main__": part_1() part_2()