-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday04.py
102 lines (85 loc) · 3.09 KB
/
day04.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
101
102
import re
from functools import reduce
from utils import transpose
with open("day04-input.txt", "r") as f:
data = f.readlines()
def extractFullSequence(data):
return [int(num) for num in data[0].strip().split(",")]
def extractBoards(data):
boards = []
for x in range(2, len(data), 6):
board = []
for y in range(5):
board.append([int(num) for num in re.split(" +", data[x + y].strip())])
boards.append(board)
return boards
# The score of the winning board can now be calculated.
# Start by finding the sum of all unmarked numbers on that board;
# in this case, the sum is 188.
# Then, multiply that sum by the number that was just called
# when the board won, 24, to get the final score, 188 * 24 = 4512.
def computeScore(board, sequence) -> int:
# sum of all unmarked numbers on that board
remainingNums = board.copy()
# Flatten the board arrays
remainingNums = reduce(lambda acc, curr: acc + curr, remainingNums)
# Remove called numbers from board
for num in sequence:
if num in remainingNums:
remainingNums.remove(num)
remainingSum = sum(remainingNums)
# the number that was just called
last = int(sequence[-1])
return remainingSum * last
def boardHasBingo(board, sequence) -> bool:
# extract board bingo lines
lines = []
for row in board:
lines.append(list(row))
transposedBoard = transpose(board)
for row in transposedBoard:
lines.append(list(row))
# cross of sequence numbers in lines
for num in sequence:
for line in lines:
if num in line:
line.remove(num)
# examine if any lines have bingo
for line in lines:
if len(line) == 0:
return True
return False
def checkBoardsForBingo(boards, sequence):
results = [boardHasBingo(board, sequence) for board in boards]
if True in results:
return results.index(True)
else:
return False
def findWinningScore(data):
boards = extractBoards(data)
sequence = extractFullSequence(data)
calledNumbers = []
winBoardIndex = False
while winBoardIndex is False:
calledNumbers.append(sequence.pop(0))
winBoardIndex = checkBoardsForBingo(boards, calledNumbers)
return computeScore(boards[winBoardIndex], calledNumbers)
def findLastPlaceScore(data):
boards = extractBoards(data)
sequence = extractFullSequence(data)
calledNumbers = []
winBoardIndex = False
lastBoard = False
while len(boards) > 0:
calledNumbers.append(sequence.pop(0))
winBoardIndex = checkBoardsForBingo(boards, calledNumbers)
while winBoardIndex is not False:
# Remove win board from list
lastBoard = boards.pop(winBoardIndex)
# Check if there are any other joint winners this round
winBoardIndex = checkBoardsForBingo(boards, calledNumbers)
# Only one board should remain
return computeScore(lastBoard, calledNumbers)
if __name__ == "__main__":
print(f"Day04a: {findWinningScore(data)}")
print(f"Day04b: {findLastPlaceScore(data)}")