-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday4_scratchcards.py
More file actions
64 lines (47 loc) · 2.04 KB
/
day4_scratchcards.py
File metadata and controls
64 lines (47 loc) · 2.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import math
import re
from typing import List, Dict
from input_files.day4_input import day4_input_string
short_input = """The author of Advent of Code, has specifically requested people to not include the input strings. So I won't."""
input_string = day4_input_string
class Card:
def __init__(self, card_id: int, winning_numbers: List[int], numbers: List[int]):
self.card_id = card_id
self.winning_numbers = winning_numbers
self.numbers = numbers
self.copies = 1
def number_of_winning_numbers(self):
return sum([1 for n in self.numbers if n in self.winning_numbers])
def points(self):
winning_numbers = self.number_of_winning_numbers()
if winning_numbers == 0:
return 0
return 1 if winning_numbers == 1 else round(math.pow(2, winning_numbers - 1))
def __repr__(self):
return f"{self.card_id}: copies={self.copies}"
def build_cards():
card_id_pattern = r"Card[ ]*(\d+)"
numbers_pattern = r"(\d+)"
cards: List[Card] = []
for line in input_string.split("\n"):
card_id = int(re.findall(card_id_pattern, line).pop())
winning_numbers_string, numbers_string = line.split(": ")[1].split("|")
winning_numbers = [int(wn) for wn in (re.findall(numbers_pattern, winning_numbers_string))]
numbers = [int(n) for n in (re.findall(numbers_pattern, numbers_string))]
cards.append(Card(card_id, winning_numbers, numbers))
return cards
def part1():
built_cards = build_cards()
return sum([c.points() for c in built_cards])
def part2():
built_cards = build_cards()
for idx, card in enumerate(built_cards):
matching_numbers = card.number_of_winning_numbers()
for n in range(0, card.copies):
for x in range(1, matching_numbers + 1):
card_to_copy_index = idx + x
if card_to_copy_index <= len(built_cards):
built_cards[card_to_copy_index].copies += 1
return sum([card.copies for card in built_cards])
print(part1())
print(part2())