advent-of-code/2023/python/day04.py

70 lines
1.9 KiB
Python
Raw Normal View History

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()