83 lines
1.9 KiB
Python
83 lines
1.9 KiB
Python
from pathlib import Path
|
|
from typing import TypedDict
|
|
|
|
|
|
class Grab(TypedDict):
|
|
red: int
|
|
blue: int
|
|
green: int
|
|
|
|
|
|
def grab_in_bag(bag: Grab, grab: Grab) -> bool:
|
|
for color, count in grab.items():
|
|
if count > bag[color]:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
class Game:
|
|
def __init__(self, id: int, grabs: list[Grab] | None = None) -> None:
|
|
self.id = id
|
|
self.grabs = grabs if grabs else []
|
|
|
|
def possible(self, bag: Grab) -> bool:
|
|
return all(grab_in_bag(bag, grab) for grab in self.grabs)
|
|
|
|
|
|
def parse_line(line: str) -> Game:
|
|
line = line.strip()
|
|
|
|
game_parsed, _, grabs = line.partition(":")
|
|
id = int("".join(c for c in game_parsed if c.isnumeric()))
|
|
|
|
game = Game(id)
|
|
|
|
for grab_draw in grabs.split(";"):
|
|
grab = Grab(red=0, blue=0, green=0)
|
|
for color_draw in grab_draw.split(","):
|
|
color_draw = color_draw.strip()
|
|
count, _, color = color_draw.partition(" ")
|
|
grab[color] = int(count)
|
|
|
|
game.grabs.append(grab)
|
|
|
|
return game
|
|
|
|
|
|
def part1(input: Path) -> int:
|
|
bag = Grab(red=12, blue=14, green=13)
|
|
|
|
total = 0
|
|
with input.open() as f:
|
|
for line in f:
|
|
game = parse_line(line)
|
|
if game.possible(bag):
|
|
total += game.id
|
|
|
|
return total
|
|
|
|
|
|
def part2(input: Path) -> int:
|
|
total = 0
|
|
with input.open() as f:
|
|
for line in f:
|
|
bag = Grab(red=0, blue=0, green=0)
|
|
game = parse_line(line)
|
|
power = 1
|
|
for color in bag:
|
|
bag[color] = max(grab[color] for grab in game.grabs)
|
|
power *= bag[color]
|
|
|
|
# print(bag, power)
|
|
total += power
|
|
|
|
return total
|
|
|
|
|
|
if __name__ == "__main__":
|
|
answer1 = part1(Path("./input.txt"))
|
|
print("part 1", answer1)
|
|
answer2 = part2(Path("./input.txt"))
|
|
print("part 2", answer2)
|