55 lines
1.6 KiB
Python
55 lines
1.6 KiB
Python
|
|
from itertools import chain
|
||
|
|
|
||
|
|
from solutions import BaseSolution
|
||
|
|
|
||
|
|
|
||
|
|
class Solution(BaseSolution):
|
||
|
|
input_file = "04.txt"
|
||
|
|
|
||
|
|
def __str__(self):
|
||
|
|
return "Day 4: Day 4: Giant Squid"
|
||
|
|
|
||
|
|
def parse_input(self, data):
|
||
|
|
queue, *boards = data.strip().split("\n\n")
|
||
|
|
queue = list(map(int, queue.split(",")))
|
||
|
|
boards = [[list(map(int, r.split())) for r in b.splitlines()] for b in boards]
|
||
|
|
return queue, boards
|
||
|
|
|
||
|
|
def solve(self, puzzle_input):
|
||
|
|
queue, boards = puzzle_input
|
||
|
|
called, winner, _i = self._play(queue, boards)
|
||
|
|
return self._score(called, winner)
|
||
|
|
|
||
|
|
def solve_again(self, puzzle_input):
|
||
|
|
queue, boards = puzzle_input
|
||
|
|
while (len(boards)) > 0:
|
||
|
|
called, winner, i = self._play(queue, boards)
|
||
|
|
del boards[i]
|
||
|
|
return self._score(called, winner)
|
||
|
|
|
||
|
|
def _score(self, called, winner):
|
||
|
|
return called[-1] * sum(set(chain(*winner)) - set(called))
|
||
|
|
|
||
|
|
def _play(self, queue, boards):
|
||
|
|
def bingo(called, numbers):
|
||
|
|
return numbers.issubset(called)
|
||
|
|
|
||
|
|
boards = list(
|
||
|
|
map(
|
||
|
|
lambda r: {"rows": list(map(set, r)), "cols": list(map(set, zip(*r)))},
|
||
|
|
boards,
|
||
|
|
)
|
||
|
|
)
|
||
|
|
for i in range(5, len(queue)):
|
||
|
|
called = queue[:i]
|
||
|
|
for i, b in enumerate(boards):
|
||
|
|
if any(bingo(called, r) for r in b["rows"]) or any(
|
||
|
|
bingo(called, c) for c in b["cols"]
|
||
|
|
):
|
||
|
|
return called, b["rows"], i
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
solution = Solution()
|
||
|
|
solution.show_results()
|