-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path04.py
67 lines (53 loc) · 1.82 KB
/
04.py
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
65
66
67
import re
from utils import rinput
RE_DIGITS = re.compile(r"(\d+)")
SQ_SIZE = 5
def parse(inp):
splits = inp.split("\n\n")
numbers = map(int, splits[0].split(","))
boards = []
for br in splits[1:]:
board = [list(map(int, RE_DIGITS.findall(row))) for row in br.split("\n")]
boards.append(board)
board_dcts = []
for brd in boards:
dct = {val: (x, y) for y, row in enumerate(brd) for x, val in enumerate(row)}
board_dcts.append(dct)
return numbers, boards, board_dcts
def has_won(marks):
for i in range(SQ_SIZE):
row = {(x, i) for x in range(SQ_SIZE)}
col = {(i, y) for y in range(SQ_SIZE)}
if row <= marks or col <= marks:
return True
return False
def sum_of_unmarked(marks, board):
return sum(
board[y][x]
for y in range(SQ_SIZE)
for x in range(SQ_SIZE)
if (x, y) not in marks
)
def solve1(numbers, boards, board_dcts):
marked = [set() for _ in range(len(board_dcts))]
for n in numbers:
for i, dct in enumerate(board_dcts):
if n in dct:
marked[i].add(dct[n])
for marks, board in zip(marked, boards):
if has_won(marks):
return n * sum_of_unmarked(marks, board)
def solve2(numbers, boards, board_dcts):
marked = [set() for _ in range(len(board_dcts))]
winners = set()
for n in numbers:
for i, dct in enumerate(board_dcts):
if n in dct:
marked[i].add(dct[n])
for i, (marks, board) in enumerate(zip(marked, boards)):
if i not in winners and has_won(marks):
winners.add(i)
if len(winners) == len(boards):
return n * sum_of_unmarked(marks, board)
print(solve1(*parse(rinput(4))))
print(solve2(*parse(rinput(4))))