After spending hours on day 7, I finished day 8 in about 15 minutes. It was simply reading in a series of numbers which represented pixels in various layers in an email. In part one I’ll break the pixels into layers, and evaluate each one. In part two, I’ll actually create the image.

## Challenge

The puzzle can be found here. I’m given a string of 0s, 1s, and 2s. The string is 15000 characters long, which I must break into layers that are 25 wide by 6 tall. In part one, I’ll find the layer with the fewest 0s, and then return the number of 1s in that layer times the number of 2s.

In part two, I’ll understand that 2 is transparent, 1 is black, and 0 is white. Looking down from the top layer, I’ll draw the picture.

## Solution

### Part 1

Python makes this so simple. I’ll read in the input, and then break it into layers. Then I can use the min command, passing it a lambda function as key. The lambda just tells it to count the number of 0.

#!/usr/bin/env python3

import sys

w, h = 25, 6
with open(sys.argv[1], "r") as f:

layers = [pixels[i : i + w * h] for i in range(0, len(pixels), w * h)]

fewest_0 = min(layers, key=lambda x: x.count("0"))
print(f"Part 1: {fewest_0.count('1')*fewest_0.count('2')}")


It runs and immediately returns the answer:

$time python3 day8.py 08-puzzle_input.txt Part 1: 1330 real 0m0.028s user 0m0.020s sys 0m0.008s  ### Part 2 I now just need to write something that will loop over the pixels, and then starting at layer 0, find the first layer with a non-2 at that pixel. #!/usr/bin/env python3 import sys w, h = 25, 6 with open(sys.argv[1], "r") as f: pixels = f.read().strip() layers = [pixels[i : i + w * h] for i in range(0, len(pixels), w * h)] fewest_0 = min(layers, key=lambda x: x.count("0")) print(f"Part 1: {fewest_0.count('1')*fewest_0.count('2')}") print(f"Part 2:") for y in range(h): line = "" for x in range(w): l = 0 while layers[l][x + (y * w)] == "2": l += 1 line += layers[l][x + (y * w)] print(line)  This prints an image, but it’s hard to read: $ time python3 day8.py 08-puzzle_input.txt
Part 1: 1330
Part 2:
1111001100100101111011110
1000010010100101000010000
1110010010111101110011100
1000011110100101000010000
1000010010100101000010000
1000010010100101111010000

real    0m0.046s
user    0m0.043s
sys     0m0.004s


I’ll replace the 0s with a unicode block character, and the 1s with a space:

print(line.replace("0", chr(9608)).replace("1", " "))


Now I get an image:

$time python3 day8.py 08-puzzle_input.txt Part 1: 1330 Part 2: ██ ██ ██ █ █ █ ████ ██ █ ██ █ ████ ████ ██ ██ █ █ ██ ██ ████ █ ██ █ ████ ████ ████ ██ █ ██ █ ████ ████ ████ ██ █ ██ █ █ ████ real 0m0.032s user 0m0.028s sys 0m0.004s  That’s getting better. It’s actually easier to read if I invest the image, switching 0 and 1: $ time python3 day8.py 08-puzzle_input.txt
Part 1: 1330
Part 2:
████  ██  █  █ ████ ████
█    █  █ █  █ █    █
███  █  █ ████ ███  ███
█    ████ █  █ █    █
█    █  █ █  █ █    █
█    █  █ █  █ ████ █

real    0m0.048s
user    0m0.044s
sys     0m0.004s


Here’s an image from my terminal in case the text doesn’t format right:

## Final Code

#!/usr/bin/env python3

import sys

w, h = 25, 6
with open(sys.argv[1], "r") as f:

layers = [pixels[i : i + w * h] for i in range(0, len(pixels), w * h)]

fewest_0 = min(layers, key=lambda x: x.count("0"))
print(f"Part 1: {fewest_0.count('1')*fewest_0.count('2')}")

print(f"Part 2:")
for y in range(h):
line = ""
for x in range(w):
l = 0
while layers[l][x + (y * w)] == "2":
l += 1
line += layers[l][x + (y * w)]
print(line.replace("1", chr(9608)).replace("0", " "))