2023-12-04 15:30:55 +00:00
|
|
|
import shared
|
|
|
|
import re
|
|
|
|
from pprint import pprint
|
|
|
|
|
|
|
|
pattern = r"Card\s+(\d+): ([\d\s]+) \| ([\d\s]+)"
|
|
|
|
|
2023-12-08 18:42:42 +00:00
|
|
|
|
2023-12-04 15:30:55 +00:00
|
|
|
def load_cards(rows):
|
|
|
|
cards = {}
|
|
|
|
for row in rows:
|
|
|
|
match = re.match(pattern, row)
|
|
|
|
card_number = int(match.group(1))
|
|
|
|
winning_numbers = set(list(map(int, match.group(2).split())))
|
|
|
|
have_numbers = set(list(map(int, match.group(3).split())))
|
|
|
|
have = winning_numbers.intersection(have_numbers)
|
|
|
|
cards[card_number] = dict(
|
|
|
|
winning_numbers=winning_numbers,
|
|
|
|
have_numbers=have_numbers,
|
|
|
|
have=have,
|
|
|
|
have_count=len(have),
|
2023-12-04 15:39:22 +00:00
|
|
|
points=0,
|
2023-12-08 18:42:42 +00:00
|
|
|
refs=0,
|
2023-12-04 15:30:55 +00:00
|
|
|
)
|
|
|
|
if have:
|
|
|
|
points = 1
|
2023-12-08 18:42:42 +00:00
|
|
|
for _ in range(len(have) - 1):
|
2023-12-04 15:30:55 +00:00
|
|
|
points *= 2
|
2023-12-08 18:42:42 +00:00
|
|
|
cards[card_number]["points"] = points
|
2023-12-04 15:30:55 +00:00
|
|
|
return cards
|
|
|
|
|
2023-12-08 18:42:42 +00:00
|
|
|
|
2023-12-04 15:30:55 +00:00
|
|
|
# @shared.profile
|
|
|
|
def part1(cards):
|
2023-12-08 18:42:42 +00:00
|
|
|
print(sum(card["points"] for _, card in cards.items()))
|
2023-12-04 15:30:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
# @shared.profile
|
|
|
|
def part2(cards):
|
2023-12-08 18:42:42 +00:00
|
|
|
card_ids = list(range(len(cards) + 1))
|
2023-12-04 15:30:55 +00:00
|
|
|
for card_id, card in cards.items():
|
2023-12-08 18:42:42 +00:00
|
|
|
nn = [x + 1 + card_id for x in range(card["have_count"])]
|
2023-12-04 15:39:22 +00:00
|
|
|
if not nn:
|
|
|
|
continue
|
2023-12-04 15:30:55 +00:00
|
|
|
|
2023-12-04 15:39:22 +00:00
|
|
|
# One point for initially having the card
|
|
|
|
for idx in nn:
|
2023-12-08 18:42:42 +00:00
|
|
|
cards[idx]["refs"] += 1
|
2023-12-04 15:39:22 +00:00
|
|
|
# X more points for how many times this card is referenced
|
2023-12-08 18:42:42 +00:00
|
|
|
for _ in range(card["refs"]):
|
2023-12-04 15:39:22 +00:00
|
|
|
for idx in nn:
|
2023-12-08 18:42:42 +00:00
|
|
|
cards[idx]["refs"] += 1
|
2023-12-04 15:39:22 +00:00
|
|
|
# Sum the ref counts, and then add the total cards in
|
2023-12-08 18:42:42 +00:00
|
|
|
print(sum(card["refs"] for _, card in cards.items()) + len(cards))
|
2023-12-04 15:30:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
rows = [row for row in shared.load_rows(4)]
|
|
|
|
cards = load_cards(rows)
|
|
|
|
with shared.elapsed_timer() as elapsed:
|
|
|
|
part1(cards)
|
|
|
|
print("🕒", elapsed())
|
|
|
|
|
|
|
|
with shared.elapsed_timer() as elapsed:
|
|
|
|
part2(cards)
|
|
|
|
print("🕒", elapsed())
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|