129 lines
3.4 KiB
Python
129 lines
3.4 KiB
Python
|
#!/usr/bin/env python
|
||
|
# 2021 - Advent Of Code - 4 part 2
|
||
|
|
||
|
import re
|
||
|
|
||
|
re_parse = re.compile(r'\s?(\d+)\s+'*4 + r'(\d+)')
|
||
|
GRID_SIZE = 5
|
||
|
|
||
|
|
||
|
class Board:
|
||
|
|
||
|
def __init__(self, grid):
|
||
|
self.grid = grid
|
||
|
self.marked = [[0] * GRID_SIZE for _ in range(GRID_SIZE)]
|
||
|
|
||
|
def print_with_mark(self):
|
||
|
for x in range(GRID_SIZE):
|
||
|
print(f'{self.grid[x]} \t {self.marked[x]}')
|
||
|
|
||
|
def mark_number(self, num):
|
||
|
for line in range(GRID_SIZE):
|
||
|
try:
|
||
|
index = self.grid[line].index(num)
|
||
|
self.marked[line][index] = 1
|
||
|
if self.has_win():
|
||
|
return True
|
||
|
return False
|
||
|
except ValueError:
|
||
|
pass
|
||
|
return False
|
||
|
|
||
|
def has_win(self):
|
||
|
# check lines
|
||
|
for line in range(GRID_SIZE):
|
||
|
if 0 not in self.marked[line]:
|
||
|
return True
|
||
|
|
||
|
# check column
|
||
|
for c in range(GRID_SIZE):
|
||
|
col_sum = 0
|
||
|
for line in range(GRID_SIZE):
|
||
|
if self.marked[line][c] == 0:
|
||
|
break
|
||
|
else:
|
||
|
col_sum += 1
|
||
|
if col_sum == GRID_SIZE:
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
def calc_unmarked(self):
|
||
|
unmarked_sum = 0
|
||
|
for line in range(GRID_SIZE):
|
||
|
for col in range(GRID_SIZE):
|
||
|
if self.marked[line][col] == 0:
|
||
|
unmarked_sum += int(self.grid[line][col])
|
||
|
return unmarked_sum
|
||
|
|
||
|
|
||
|
def parse_file(file):
|
||
|
boards_list = []
|
||
|
with open(file) as f:
|
||
|
numbers = f.readline().split(',')
|
||
|
|
||
|
line = f.readline()
|
||
|
while line:
|
||
|
board = []
|
||
|
for i in range(GRID_SIZE):
|
||
|
line = f.readline()
|
||
|
m = re_parse.match(line)
|
||
|
grid_line = m.groups()
|
||
|
board.append(grid_line)
|
||
|
|
||
|
b = Board(board)
|
||
|
boards_list.append(b)
|
||
|
line = f.readline()
|
||
|
return boards_list, numbers
|
||
|
|
||
|
|
||
|
def play_until_win(boards_list, draws):
|
||
|
""" play until win and return last pos """
|
||
|
|
||
|
for d in draws:
|
||
|
for board in boards_list:
|
||
|
if board.mark_number(d):
|
||
|
print("this board wins !")
|
||
|
board.print_with_mark()
|
||
|
return board, d
|
||
|
|
||
|
|
||
|
def play(boards_list, draws):
|
||
|
""" call all numbers
|
||
|
could stop when all boards have won ;-) """
|
||
|
|
||
|
winners = []
|
||
|
for d in draws:
|
||
|
print(f'calling {d}')
|
||
|
winner = ()
|
||
|
round_winners = []
|
||
|
for board in boards_list:
|
||
|
if board.mark_number(d):
|
||
|
print("this board wins !")
|
||
|
board.print_with_mark()
|
||
|
winner = (board, d)
|
||
|
round_winners.append(winner)
|
||
|
|
||
|
if winner:
|
||
|
print(f'round winners: {len(round_winners)}')
|
||
|
for r in round_winners:
|
||
|
boards_list.remove(r[0])
|
||
|
winners.extend(round_winners)
|
||
|
|
||
|
print(f'number of winners: {len(winners)}')
|
||
|
return winners
|
||
|
|
||
|
|
||
|
boards, draws = parse_file('input.txt')
|
||
|
print(f'number of boards: {len(boards)}')
|
||
|
|
||
|
# (winning_board, last_num) = play_until_win(boards, draws)
|
||
|
winning_boards = play(boards, draws)
|
||
|
|
||
|
winning_board, last_num = winning_boards[-1]
|
||
|
print(f'last number is: {last_num}')
|
||
|
board_score = winning_board.calc_unmarked()
|
||
|
print(f'board score: {board_score}')
|
||
|
|
||
|
score = int(last_num) * board_score
|
||
|
print(f'score is : {score}')
|