From 661440e4cee68d130974bc9f322f15b219645680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Ytterstr=C3=B6m?= Date: Sat, 4 Dec 2021 07:12:00 +0100 Subject: [PATCH] Solve 2021:4 "Giant squid" --- 2021-python/solutions/day_04.py | 54 +++++++++++++++++++++++++++++ 2021-python/tests/test_day_04.py | 59 ++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 2021-python/solutions/day_04.py create mode 100644 2021-python/tests/test_day_04.py diff --git a/2021-python/solutions/day_04.py b/2021-python/solutions/day_04.py new file mode 100644 index 0000000..9b3aa4b --- /dev/null +++ b/2021-python/solutions/day_04.py @@ -0,0 +1,54 @@ +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() diff --git a/2021-python/tests/test_day_04.py b/2021-python/tests/test_day_04.py new file mode 100644 index 0000000..882c64e --- /dev/null +++ b/2021-python/tests/test_day_04.py @@ -0,0 +1,59 @@ +import unittest + +from solutions.day_04 import Solution + + +class Day04TestCase(unittest.TestCase): + def setUp(self): + self.solution = Solution() + self.puzzle_input = self.solution.parse_input( + """ + 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 + """ + ) + + def test_parse_puzzle_input(self): + data = """ + 7,4,9 + +22 13 17 11 0 + 8 2 23 4 24 + + 3 15 0 2 22 + 9 18 13 17 5 + """ + assert self.solution.parse_input(data) == ( + [7, 4, 9], + [ + [[22, 13, 17, 11, 0], [8, 2, 23, 4, 24]], + [[3, 15, 0, 2, 22], [9, 18, 13, 17, 5]], + ], + ) + + def test_solve_first_part(self): + assert self.solution.solve(self.puzzle_input) == 188 * 24 + + def test_solve_second_part(self): + assert self.solution.solve_again(self.puzzle_input) == 148 * 13 + + +if __name__ == "__main__": + unittest.main()