113 lines
2.9 KiB
Python
113 lines
2.9 KiB
Python
from pprint import pprint
|
|
|
|
|
|
WIDTH = 5
|
|
HEIGHT = 5
|
|
|
|
|
|
class Board(object):
|
|
def __init__(self, matrix, win_matrix):
|
|
# matrix: map of num => (x,y)
|
|
# win_matrix: map of (x,y) => picked bool
|
|
self.matrix = matrix
|
|
self.win_matrix = win_matrix
|
|
self.total = None # this is calculated upon noticing the board has won
|
|
|
|
@staticmethod
|
|
def from_block(block):
|
|
# convert the block, which is an array of string, into a flat list of numbers
|
|
nums = []
|
|
for row in block:
|
|
nums.extend([int(i) for i in row.strip().split()])
|
|
|
|
i = 0
|
|
matrix = {}
|
|
win_matrix = {}
|
|
for y in range(0, HEIGHT):
|
|
for x in range(0, WIDTH):
|
|
sq = nums[i]
|
|
matrix[sq] = (x, y, )
|
|
win_matrix[(x, y, )] = False
|
|
i += 1
|
|
|
|
return Board(matrix, win_matrix)
|
|
|
|
def fill(self, num):
|
|
# mark the space with $num as filled
|
|
# return whether this makes the board a winner
|
|
try:
|
|
filled_position = self.matrix[num]
|
|
except KeyError:
|
|
return False # number not on this board
|
|
self.win_matrix[filled_position] = True
|
|
return self.check_solved(num, *filled_position)
|
|
|
|
def check_solved(self, num, new_x, new_y):
|
|
# the square at ($new_x, $new_y) has been filled, check if it solves the board
|
|
# it solves the board if:
|
|
# the row is filled
|
|
# the col is filled
|
|
# either diagonal is filled ----- jk, the problem says diagonals dont matter
|
|
w = any([
|
|
# row
|
|
all([self.win_matrix[(x_coord, new_y, )] for x_coord in range(0, WIDTH)]),
|
|
# col
|
|
all([self.win_matrix[(new_x, y_coord, )] for y_coord in range(0, HEIGHT)])
|
|
])
|
|
if w:
|
|
self.total = self.calc_total(num)
|
|
return w
|
|
|
|
def calc_total(self, num):
|
|
print("calculating total")
|
|
# sum of all unmarked nums
|
|
unmarked = 0
|
|
for sq_num, coord in self.matrix.items():
|
|
if not self.win_matrix[coord]:
|
|
unmarked += sq_num
|
|
return unmarked * num
|
|
|
|
|
|
def update_boards(boards, pick):
|
|
winners = []
|
|
for board in boards:
|
|
if board.fill(pick):
|
|
winners.append(board)
|
|
|
|
return winners
|
|
|
|
|
|
with open("input.txt") as f:
|
|
lines = [i for i in f.readlines()]
|
|
|
|
|
|
# input parser
|
|
picks = [int(i) for i in lines.pop(0).strip().split(",")]
|
|
lines.pop(0)
|
|
|
|
board_blocks = []
|
|
|
|
while True:
|
|
# pop the 5 expected lines for the board
|
|
board_blocks.append([lines.pop(0), lines.pop(0), lines.pop(0), lines.pop(0), lines.pop(0), ])
|
|
if not lines:
|
|
break
|
|
empty = lines.pop(0)
|
|
|
|
|
|
boards = []
|
|
|
|
for block in board_blocks:
|
|
boards.append(Board.from_block(block))
|
|
|
|
|
|
for pick_num, pick in enumerate(picks):
|
|
winners = update_boards(boards, pick)
|
|
print("x")
|
|
if winners:
|
|
print(winners)
|
|
print(winners[0].total)
|
|
break
|
|
|
|
|