summaryrefslogtreecommitdiffstats
path: root/day4/__init__.py
diff options
context:
space:
mode:
authorGravatar Tom van der Lee <tom@vanderlee.io>2021-12-04 12:31:52 +0100
committerGravatar Tom van der Lee <tom@vanderlee.io>2021-12-04 12:31:52 +0100
commit5ba784ae1220ec930ffce9ea1ccbb1d6411f841e (patch)
tree2c11dce971ce179e3c2b9c022970d2e57fc7eb23 /day4/__init__.py
parent3df1c0af382c6c04370b879c7168b46d833c761f (diff)
download2021-5ba784ae1220ec930ffce9ea1ccbb1d6411f841e.tar.gz
2021-5ba784ae1220ec930ffce9ea1ccbb1d6411f841e.tar.bz2
2021-5ba784ae1220ec930ffce9ea1ccbb1d6411f841e.zip
Day 4
Diffstat (limited to 'day4/__init__.py')
-rw-r--r--day4/__init__.py121
1 files changed, 121 insertions, 0 deletions
diff --git a/day4/__init__.py b/day4/__init__.py
new file mode 100644
index 0000000..74c01f1
--- /dev/null
+++ b/day4/__init__.py
@@ -0,0 +1,121 @@
1from collections import Counter
2from copy import copy
3from dataclasses import dataclass
4from typing import Iterator, List, Optional, Tuple, Callable
5
6from aoc import BaseAssignment
7
8def bold(item: str, condition: Callable[[], bool]):
9 return f'\033[36m{item}\033[0m' if condition() else item
10
11@dataclass
12class Number:
13 nr: int
14 marked: bool = False
15
16 def __int__(self):
17 return self.nr
18
19 def __bool__(self):
20 return self.marked
21
22 def __radd__(self, other):
23 return other + int(self)
24
25 def mark(self):
26 self.marked = True
27
28@dataclass
29class BingoCard:
30 card: List[List[Number]]
31
32 @property
33 def bingo(self) -> bool:
34 return any([
35 *[all(bool(item) for item in row) for row in self.card],
36 *[all(bool(row[col_index]) for row in self.card) for col_index in range(5)]
37 ])
38
39 def mark(self, nr: int):
40 for row in self.card:
41 for item in row:
42 if int(item) == nr:
43 item.mark()
44
45 @property
46 def unmarked(self):
47 return [
48 item
49 for row in self.card
50 for item in row
51 if not bool(item)
52 ]
53
54 def __str__(self):
55 return '\n'.join([
56 ''.join([
57 bold(str(int(item)).rjust(2, ' ').ljust(3, ' '), lambda: item.marked)
58 for item in row
59 ])
60 for row in self.card
61 ])
62
63
64class Assignment(BaseAssignment):
65 def read_input(self, example = False) -> Tuple[List[int], List[BingoCard]]:
66 cards = []
67 card = None
68
69 input = super().read_input(example)
70 nrs = [ int(n) for n in next(input).split(',') ]
71
72 try:
73 row = next(input)
74
75 while True:
76 if row == '':
77 if card is not None:
78 cards.append(BingoCard(card=card))
79 card = []
80 else:
81 card.append([ Number(nr=int(item)) for item in row.split(' ') if item != ''])
82
83 row = next(input)
84
85 except StopIteration:
86 if card is not None:
87 cards.append(BingoCard(card=card))
88
89 return nrs, cards
90
91
92class AssignmentOne(Assignment):
93 example_result = 4512
94
95 def run(self, input: Tuple[List[int], List[BingoCard]]) -> int:
96 nrs, cards = input
97
98 for nr in nrs:
99 for card in cards:
100 card.mark(nr)
101
102 if card.bingo:
103 return nr * sum(card.unmarked)
104
105
106class AssignmentTwo(Assignment):
107 example_result = 1924
108
109 def run(self, input: Tuple[List[int], List[BingoCard]]) -> int:
110 nrs, cards = input
111
112 in_game = copy(cards)
113 for nr in nrs:
114 for card in copy(in_game):
115 card.mark(nr)
116
117 if card.bingo:
118 in_game.remove(card)
119
120 if len(in_game) == 0:
121 return nr * sum(card.unmarked) \ No newline at end of file