163 lines
5.2 KiB
Python
163 lines
5.2 KiB
Python
# --- Day 6: Probably a Fire Hazard ---
|
|
|
|
# Because your neighbors keep defeating you in the holiday house decorating
|
|
# contest year after year, you've decided to deploy one million lights in a
|
|
# 1000x1000 grid.
|
|
|
|
# Furthermore, because you've been especially nice this year, Santa has mailed
|
|
# you instructions on how to display the ideal lighting configuration.
|
|
|
|
# Lights in your grid are numbered from 0 to 999 in each direction; the lights
|
|
# at each corner are at 0,0, 0,999, 999,999, and 999,0. The instructions
|
|
# include whether to turn on, turn off, or toggle various inclusive ranges
|
|
# given as coordinate pairs. Each coordinate pair represents opposite corners
|
|
# of a rectangle, inclusive; a coordinate pair like 0,0 through 2,2 therefore
|
|
# refers to 9 lights in a 3x3 square. The lights all start turned off.
|
|
|
|
# To defeat your neighbors this year, all you have to do is set up your lights
|
|
# by doing the instructions Santa sent you in order.
|
|
|
|
# For example:
|
|
|
|
# turn on 0,0 through 999,999 would turn on (or leave on) every light.
|
|
# toggle 0,0 through 999,0 would toggle the first line of 1000 lights,
|
|
# turning off the ones that were on, and turning on the ones that were off.
|
|
# turn off 499,499 through 500,500 would turn off (or leave off) the
|
|
# middle four lights.
|
|
|
|
# After following the instructions, how many lights are lit?
|
|
|
|
from collections import defaultdict
|
|
|
|
with open("files/P6.txt") as f:
|
|
instructions = [line for line in f.read().strip().split("\n")]
|
|
|
|
# print(instructions)
|
|
|
|
|
|
def get_coordinates(s: str) -> tuple[str, int, int, int, int]:
|
|
if s.startswith(("turn off", "turn on")):
|
|
_s = s.split()
|
|
action = _s[1]
|
|
x1, x2 = _s[2].split(",")
|
|
y1, y2 = _s[4].split(",")
|
|
return action, int(x1), int(x2), int(y1), int(y2)
|
|
if s.startswith("toggle"):
|
|
_s = s.split()
|
|
action = _s[0]
|
|
x1, x2 = _s[1].split(",")
|
|
y1, y2 = _s[3].split(",")
|
|
return action, int(x1), int(x2), int(y1), int(y2)
|
|
|
|
|
|
def apply_action(
|
|
action: str,
|
|
coords: list[int],
|
|
grid: dict[tuple[int, int], int],
|
|
) -> dict[tuple[int, int], int]:
|
|
if action == "off":
|
|
for x in range(coords[0], coords[2] + 1):
|
|
for y in range(coords[1], coords[3] + 1):
|
|
grid[x, y] = 0
|
|
return grid
|
|
elif action == "on":
|
|
for x in range(coords[0], coords[2] + 1):
|
|
for y in range(coords[1], coords[3] + 1):
|
|
grid[x, y] = 1
|
|
return grid
|
|
elif action == "toggle":
|
|
for x in range(coords[0], coords[2] + 1):
|
|
for y in range(coords[1], coords[3] + 1):
|
|
if grid[x, y] == 1:
|
|
grid[x, y] = 0
|
|
elif grid[x, y] == 0:
|
|
grid[x, y] = 1
|
|
return grid
|
|
|
|
|
|
def part_1():
|
|
# Initially, all lights are off("0")
|
|
grid = defaultdict(int)
|
|
for x in range(1000):
|
|
for y in range(1000):
|
|
grid[x, y] = 0
|
|
|
|
for instruction in instructions:
|
|
action, *coords = get_coordinates(instruction)
|
|
grid = apply_action(action, coords, grid)
|
|
|
|
lit = sum(1 for value in grid.values() if value == 1)
|
|
print(f"There are {lit} ligths lit")
|
|
|
|
|
|
# --- Part Two ---
|
|
|
|
# You just finish implementing your winning light pattern when you realize you
|
|
# mistranslated Santa's message from Ancient Nordic Elvish.
|
|
|
|
# The light grid you bought actually has individual brightness controls; each
|
|
# light can have a brightness of zero or more. The lights all start at zero.
|
|
|
|
# The phrase turn on actually means that you should increase the brightness of
|
|
# those lights by 1.
|
|
|
|
# The phrase turn off actually means that you should decrease the brightness of
|
|
# those lights by 1, to a minimum of zero.
|
|
|
|
# The phrase toggle actually means that you should increase the brightness of
|
|
# those lights by 2.
|
|
|
|
# What is the total brightness of all lights combined after following Santa's
|
|
# instructions?
|
|
|
|
# For example:
|
|
|
|
# turn on 0,0 through 0,0 would increase the total brightness by 1.
|
|
# toggle 0,0 through 999,999 would increase the total brightness by
|
|
# 2000000.
|
|
|
|
|
|
def apply_action_(
|
|
action: str,
|
|
coords: list[int],
|
|
grid: dict[tuple[int, int], int],
|
|
) -> dict[tuple[int, int], int]:
|
|
if action == "off":
|
|
for x in range(coords[0], coords[2] + 1):
|
|
for y in range(coords[1], coords[3] + 1):
|
|
if grid[x, y] != 0:
|
|
grid[x, y] -= 1
|
|
else:
|
|
grid[x, y] = 0
|
|
return grid
|
|
elif action == "on":
|
|
for x in range(coords[0], coords[2] + 1):
|
|
for y in range(coords[1], coords[3] + 1):
|
|
grid[x, y] += 1
|
|
return grid
|
|
elif action == "toggle":
|
|
for x in range(coords[0], coords[2] + 1):
|
|
for y in range(coords[1], coords[3] + 1):
|
|
grid[x, y] += 2
|
|
return grid
|
|
|
|
|
|
def part_2():
|
|
# Initially, all lights are off("0")
|
|
grid = defaultdict(int)
|
|
for x in range(1000):
|
|
for y in range(1000):
|
|
grid[x, y] = 0
|
|
|
|
for instruction in instructions:
|
|
action, *coords = get_coordinates(instruction)
|
|
grid = apply_action_(action, coords, grid)
|
|
|
|
brightness = sum(value for value in grid.values())
|
|
print(f"The total brightness is {brightness}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
part_1()
|
|
part_2()
|