Solution to problem 4 part 1 in Python and WIP for part 2)
This commit is contained in:
parent
13c4f1bced
commit
263e451804
202
src/Year_2021/P4.py
Normal file
202
src/Year_2021/P4.py
Normal file
@ -0,0 +1,202 @@
|
||||
# --- Day 4: Giant Squid ---
|
||||
|
||||
# You're already almost 1.5km (almost a mile) below the surface of the ocean,
|
||||
# already so deep that you can't see any sunlight. What you can see, however,
|
||||
# is a giant squid that has attached itself to the outside of your submarine.
|
||||
|
||||
# Maybe it wants to play bingo?
|
||||
|
||||
# Bingo is played on a set of boards each consisting of a 5x5 grid of numbers.
|
||||
# Numbers are chosen at random, and the chosen number is marked on all boards
|
||||
# on which it appears. (Numbers may not appear on all boards.) If all numbers
|
||||
# in any row or any column of a board are marked, that board wins. (Diagonals
|
||||
# don't count.)
|
||||
|
||||
# The submarine has a bingo subsystem to help passengers (currently, you and
|
||||
# the giant squid) pass the time. It automatically generates a random order in
|
||||
# which to draw numbers and a random set of boards (your puzzle input). For
|
||||
# example:
|
||||
|
||||
# 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
|
||||
|
||||
# After the first five numbers are drawn (7, 4, 9, 5, and 11), there are no
|
||||
# winners, but the boards are marked as follows (shown here adjacent to each
|
||||
# other to save space):
|
||||
|
||||
# 22 13 17 11 0 3 15 0 2 22 14 21 17 24 4
|
||||
# 8 2 23 4 24 9 18 13 17 5 10 16 15 9 19
|
||||
# 21 9 14 16 7 19 8 7 25 23 18 8 23 26 20
|
||||
# 6 10 3 18 5 20 11 10 24 4 22 11 13 6 5
|
||||
# 1 12 20 15 19 14 21 16 12 6 2 0 12 3 7
|
||||
|
||||
# After the next six numbers are drawn (17, 23, 2, 0, 14, and 21), there are
|
||||
# still no winners:
|
||||
|
||||
# 22 13 17 11 0 3 15 0 2 22 14 21 17 24 4
|
||||
# 8 2 23 4 24 9 18 13 17 5 10 16 15 9 19
|
||||
# 21 9 14 16 7 19 8 7 25 23 18 8 23 26 20
|
||||
# 6 10 3 18 5 20 11 10 24 4 22 11 13 6 5
|
||||
# 1 12 20 15 19 14 21 16 12 6 2 0 12 3 7
|
||||
|
||||
# Finally, 24 is drawn:
|
||||
|
||||
# 22 13 17 11 0 3 15 0 2 22 14 21 17 24 4
|
||||
# 8 2 23 4 24 9 18 13 17 5 10 16 15 9 19
|
||||
# 21 9 14 16 7 19 8 7 25 23 18 8 23 26 20
|
||||
# 6 10 3 18 5 20 11 10 24 4 22 11 13 6 5
|
||||
# 1 12 20 15 19 14 21 16 12 6 2 0 12 3 7
|
||||
|
||||
# At this point, the third board wins because it has at least one complete row
|
||||
# or column of marked numbers (in this case, the entire top row is marked:
|
||||
# 14 21 17 24 4).
|
||||
|
||||
# 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.
|
||||
|
||||
# To guarantee victory against the giant squid, figure out which board will win
|
||||
# first. What will your final score be if you choose that board?
|
||||
|
||||
from itertools import chain, zip_longest
|
||||
|
||||
with open("files/P4.txt", "r") as f:
|
||||
data = [line for line in f.read().strip().split("\n\n")]
|
||||
numbers, all_boards = data[0].split(","), [
|
||||
board.split("\n") for board in data[1:]
|
||||
]
|
||||
|
||||
|
||||
def iter_to_list(lst):
|
||||
return [tuple(tup.split()) for tup in lst]
|
||||
|
||||
|
||||
def transpose_board(lst):
|
||||
args = iter_to_list(lst)
|
||||
return list(zip_longest(*args))
|
||||
|
||||
|
||||
def check_num(board, number):
|
||||
flatten_list = list(chain.from_iterable(board))
|
||||
for num in flatten_list:
|
||||
if int(num.rjust(2, "0")) == int(number):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def complete_row(lst, board):
|
||||
for num in lst:
|
||||
if num not in board:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def sum_board(board, row, lst):
|
||||
flatten_list = set(chain.from_iterable(board))
|
||||
row_set = set(row)
|
||||
remain = flatten_list - row_set
|
||||
return sum(int(number) for number in list(remain) if number not in lst)
|
||||
|
||||
|
||||
boards = [iter_to_list(board) for board in all_boards]
|
||||
boards_transpose = [transpose_board(board) for board in all_boards]
|
||||
|
||||
|
||||
def part_1():
|
||||
numbers_drawn = []
|
||||
for number in numbers:
|
||||
numbers_drawn.append(number)
|
||||
if len(numbers_drawn) < 5:
|
||||
continue
|
||||
for b, bt in zip(boards, boards_transpose):
|
||||
for row_b, row_bt in zip(b, bt):
|
||||
if complete_row(row_b, numbers_drawn):
|
||||
return print(
|
||||
sum_board(b, row_b, numbers_drawn)
|
||||
* int(numbers_drawn[-1])
|
||||
)
|
||||
if complete_row(row_bt, numbers_drawn):
|
||||
return print(
|
||||
sum_board(bt, row_bt, numbers_drawn)
|
||||
* int(numbers_drawn[-1])
|
||||
)
|
||||
|
||||
|
||||
# --- Part Two ---
|
||||
|
||||
# On the other hand, it might be wise to try a different strategy: let the
|
||||
# giant squid win.
|
||||
|
||||
# You aren't sure how many bingo boards a giant squid could play at once, so
|
||||
# rather than waste time counting its arms, the safe thing to do is to figure
|
||||
# out which board will win last and choose that one. That way, no matter which
|
||||
# boards it picks, it will win for sure.
|
||||
|
||||
# In the above example, the second board is the last to win, which happens
|
||||
# after 13 is eventually called and its middle column is completely marked. If
|
||||
# you were to keep playing until this point, the second board would have a sum
|
||||
# of unmarked numbers equal to 148 for a final score of 148 * 13 = 1924.
|
||||
|
||||
# Figure out which board will win last. Once it wins, what would its final
|
||||
# score be?
|
||||
|
||||
|
||||
def part_2():
|
||||
(numbers_drawn,) = []
|
||||
for number in numbers:
|
||||
numbers_drawn.append(number)
|
||||
if len(numbers_drawn) < 5:
|
||||
continue
|
||||
for b, bt in zip(boards, boards_transpose):
|
||||
for row_b, row_bt in zip(b, bt):
|
||||
if complete_row(row_b, numbers_drawn):
|
||||
# wining_boards.append(
|
||||
# (b, row_b, numbers_drawn[-1], numbers_drawn)
|
||||
# )
|
||||
total = print(
|
||||
sum_board(b, row_b, numbers_drawn)
|
||||
* int(numbers_drawn[-1])
|
||||
)
|
||||
if total is not None and total > 0:
|
||||
print(total)
|
||||
if complete_row(row_bt, numbers_drawn):
|
||||
# wining_boards.append(
|
||||
# (bt, row_bt, numbers_drawn[-1], numbers_drawn)
|
||||
# )
|
||||
total = print(
|
||||
sum_board(bt, row_bt, numbers_drawn)
|
||||
* int(numbers_drawn[-1])
|
||||
)
|
||||
if total is not None and total > 0:
|
||||
print(total)
|
||||
# b, r, n, nd = wining_boards[0]
|
||||
# # print(b, r, n)
|
||||
# print(sum_board(b, r, nd) * int(n))
|
||||
# # last_board, row = wining_boards[-1]
|
||||
# # print(last_board, row, numbers_drawn[-1])
|
||||
# # return print(sum_board(last_board, row, numbers_drawn)) * int(
|
||||
# # numbers_drawn[-1]
|
||||
# # )
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
part_1()
|
||||
part_2()
|
Loading…
Reference in New Issue
Block a user