18
loading...
This website collects cookies to deliver better user experience
7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19
3 15 0 2 22
9 18 13 17 5
19 8 7 25 23
20 11 10 24 4
14 21 16 12 6
14 21 17 24 4
10 16 15 9 19
18 8 23 26 20
22 11 13 6 5
2 0 12 3 7
fp.readline()
which reads a single line of text from an open file. We can .split(",")
this string to chop it up into individual values, and then we can apply int()
to each of those elements (using map()
) to turn it back into a number. (the extra list()
is needed to turn the iterator returned by map()
into an actual list, since we have to use this list twice.with open("day_4.txt") as fp:
draws = list(map(int, fp.readline().split(",")))
np.mat()
function, which takes a space/semicolon separated string and turns it into a numpy matrix. For example: np.mat("1 2 3; 4 5 6; 7 8 9")
returns a 3x3 matrix with those numbers in it.fp.read()
which by default reads all the lines of the open file as an array of strings, and split it using double newlines: fp.read()[1:-1].split("\n\n")
(we have to ignore the first and last entry of the file to avoid the empty lines[
'90 8 2 34 41\n11 67 74 71 62\n47 42 44 1 17\n21 55 12 91 6\n60 69 75 92 56',
'49 29 60 45 31\n94 51 73 33 67\n21 92 53 95 96\n 2 55 52 8 87\n 4 36 76 83 42', '23 66 50 84 58\n62 98 81 76 57\n24 2 56 79 6\n55 0 16 64 38\n12 67 5 97 60',
np.mat()
to retrieve a numpy matrix of the data.with open("day_4.txt") as fp:
draws = list(map(int, fp.readline().split(",")))
boards = [np.mat(board.replace("\n", ";")) for board in fp.read()[1:-1].split("\n\n")]
masked_array()
which will maintain a matrix or array and a mask, allowing you to easily mask the data or get the sum of unmasked data.np.ma.masked_array(board)
which initializes the mask to all False
. We'll use False
as meaning "not yet drawn", and True
as "drawn".draw
is inside the mask, we can do board.data == draw
(board.data
in a masked array is the original unmasked data) this will return a 5x5 matrix of False
or True
if that element matches. So something like:matrix([[False, False, False, False, False],
[False, False, False, False, False],
[False, True, False, False, False],
[False, False, False, False, False],
[False, False, False, False, False]])
board.mask |= board.data == draw
. This will perform a binary OR operation between the above, and the current mask. In effect, it'll turn the mask to True
for any value matching the draw. As the game progresses, more and more of the mask will be turned to True
.sum(axis)
method to sum the mask along certain axes. It'll do all five rows or columns at once. so, board.mask.sum(0)
will give us how many masked values are in each column. If the mask was the above, then:matrix([[0, 1, 0, 0, 0]])
matrix([[0],
[0],
[1],
[0],
[0]])
if np.any(board.mask.sum(0) == 5) or np.any(board.mask.sum(5) == 0):
for draw, board in product(draws, [np.ma.masked_array(board) for board in boards]):
board.mask |= board.data == draw
if np.any(board.mask.sum(0) == 5) or np.any(board.mask.sum(1) == 5):
result = board.sum()*draw
break
itertools.product
to combine the for
loops for both the draw
and the board
, this makes it a bit easier to break out of the loop.sum()
method which will sum unmasked numbers directly, so the result can be simply calculated above as board.sum()*draw
won_boards = set()
for draw, (idx, board) in product(draws, enumerate([np.ma.masked_array(board) for board in boards])):
board.mask |= board.data == draw
if np.any(board.mask.sum(0) == 5) or np.any(board.mask.sum(1) == 5):
if idx not in won_boards and len(won_boards) == len(boards) -1:
result = board.sum()*draw
break
won_boards.add(idx)
won_boards
set. Next, we also fetch the index number of the board using an enumerate()
on the boards. This index is what is added to won_boards
if the board wins. Then, the last win can be detected using if idx not in won_boards and len(won_boards) == len(boards) -1:
, giving us the result of the last win.import numpy as np
from itertools import product
with open("day_4.txt") as fp:
draws = list(map(int, fp.readline().split(",")))
boards = [np.mat(board.replace("\n", ";")) for board in fp.read()[1:-1].split("\n\n")]
for draw, board in product(draws, [np.ma.masked_array(board) for board in boards]):
board.mask |= board.data == draw
if np.any(board.mask.sum(0) == 5) or np.any(board.mask.sum(1) == 5):
result = board.sum()*draw
break
print("Part 1 result:", result)
won_boards = set()
for draw, (idx, board) in product(draws, enumerate([np.ma.masked_array(board) for board in boards])):
board.mask |= board.data == draw
if np.any(board.mask.sum(0) == 5) or np.any(board.mask.sum(1) == 5):
if idx not in won_boards and len(won_boards) == len(boards) -1:
result = board.sum()*draw
break
won_boards.add(idx)
print("Part 2 result:", result)