2023-12-02 08:47:52 +00:00
|
|
|
import operator
|
|
|
|
import sys
|
|
|
|
from functools import reduce
|
|
|
|
from typing import Literal, TypeAlias, cast
|
|
|
|
|
2023-12-04 18:30:44 +00:00
|
|
|
CubeType: TypeAlias = Literal["red", "blue", "green"]
|
2023-12-02 08:47:52 +00:00
|
|
|
|
2023-12-04 18:30:44 +00:00
|
|
|
MAX_CUBES: dict[CubeType, int] = {"red": 12, "green": 13, "blue": 14}
|
2023-12-02 08:47:52 +00:00
|
|
|
|
2023-12-04 18:30:44 +00:00
|
|
|
# parse games
|
|
|
|
lines = sys.stdin.read().splitlines()
|
|
|
|
games: dict[int, list[dict[CubeType, int]]] = {}
|
2023-12-02 08:47:52 +00:00
|
|
|
for line in filter(bool, lines):
|
|
|
|
id_part, sets_part = line.split(":")
|
|
|
|
|
2023-12-04 18:30:44 +00:00
|
|
|
games[int(id_part.split(" ")[-1])] = [
|
|
|
|
{
|
|
|
|
cast(CubeType, s[1]): int(s[0])
|
|
|
|
for cube_draw in cube_set_s.strip().split(", ")
|
|
|
|
if (s := cube_draw.split(" "))
|
|
|
|
}
|
|
|
|
for cube_set_s in sets_part.strip().split(";")
|
|
|
|
]
|
2023-12-02 08:47:52 +00:00
|
|
|
|
|
|
|
# part 1
|
|
|
|
answer_1 = sum(
|
2023-12-04 18:30:44 +00:00
|
|
|
id
|
|
|
|
for id, set_of_cubes in games.items()
|
2023-12-02 08:47:52 +00:00
|
|
|
if all(
|
|
|
|
n_cubes <= MAX_CUBES[cube]
|
2023-12-04 18:30:44 +00:00
|
|
|
for cube_set in set_of_cubes
|
2023-12-02 08:47:52 +00:00
|
|
|
for cube, n_cubes in cube_set.items()
|
|
|
|
)
|
|
|
|
)
|
|
|
|
print(f"answer 1 is {answer_1}")
|
|
|
|
|
|
|
|
# part 2
|
|
|
|
answer_2 = sum(
|
|
|
|
reduce(
|
|
|
|
operator.mul,
|
2023-12-04 18:30:44 +00:00
|
|
|
(max(cube_set.get(cube, 0) for cube_set in set_of_cubes) for cube in MAX_CUBES),
|
2023-12-02 08:47:52 +00:00
|
|
|
)
|
2023-12-04 18:30:44 +00:00
|
|
|
for set_of_cubes in games.values()
|
2023-12-02 08:47:52 +00:00
|
|
|
)
|
|
|
|
print(f"answer 2 is {answer_2}")
|