-
Notifications
You must be signed in to change notification settings - Fork 0
/
04-giant-squid.py
101 lines (81 loc) · 2.79 KB
/
04-giant-squid.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import os
FILENAME = os.path.splitext(__file__)
PUZZLE_INPUT = os.path.join('.', 'puzzle-inputs', f'{FILENAME[0]}.txt')
with open(PUZZLE_INPUT, 'r') as f:
puzzle_input = f.read()
class Card:
def __init__(self, board):
self.board = board
self.num_index = dict()
self.index_board()
def index_board(self):
for i in range(5):
for j in range(5):
num = self.board[i][j]
self.num_index[num] = (i, j)
def mark_number(self, target):
if target in self.num_index:
i, j = self.num_index[target]
self.board[i][j] = 'x'
return i, j
return
def has_won(self, i, j):
"""
Checks whether self.board[i] is a winning row and checks if self.baord[k][j] is
a winning column
"""
completed = ['x',] * 5
if self.board[i] == completed:
return True
col = [self.board[k][j] for k in range(5)]
if col == completed:
return True
return False
def sum_unmarked(self):
res = 0
for row in self.board:
for num in row:
if num != 'x':
res += int(num)
return res
class Bingo:
def __init__(self, puzzle_input):
self.puzzle_input = puzzle_input
self.game_numbers = []
self.cards = []
self.load_game()
def load_game(self):
game = puzzle_input.split('\n\n')
self.game_numbers = game[0].split(',')
boards = game[1:]
for board in boards:
board = board.split()
self.cards.append(Card([board[i:i+5] for i in range(0, 25, 5)]))
def play_to_win(self):
for num in self.game_numbers:
for card in self.cards:
coordinates = card.mark_number(num)
if coordinates is not None:
i, j = coordinates
if card.has_won(i, j):
return card.sum_unmarked() * int(num)
def play_to_lose(self):
finished_cards = set()
for num in self.game_numbers:
for card_num, card in enumerate(self.cards):
if card_num in finished_cards:
continue
coordinates = card.mark_number(num)
if coordinates is not None:
i, j = coordinates
if card.has_won(i, j):
if len(finished_cards) == len(self.cards) - 1:
return card.sum_unmarked() * int(num)
else:
finished_cards.add(card_num)
def solution_one():
bingo = Bingo(puzzle_input)
return bingo.play_to_win()
def solution_two():
bingo = Bingo(puzzle_input)
return bingo.play_to_lose()