From f82b6cd9b55c79e44a5811868335b6cecb05d12d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Ytterstr=C3=B6m?= Date: Sun, 5 Dec 2021 08:30:54 +0100 Subject: [PATCH] Solve 2021:5 "Hydrothermal Venture" Tricky part, got the test data correct at part 1 long before the actual input gace the correct answers. Pure luck I guess. Part 2 I got stuck on, and resolved to visualization by a loop of prints. --- 2021-python/solutions/day_05.py | 55 ++++++++++++++++++++++++++++++++ 2021-python/tests/test_day_05.py | 39 ++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 2021-python/solutions/day_05.py create mode 100644 2021-python/tests/test_day_05.py diff --git a/2021-python/solutions/day_05.py b/2021-python/solutions/day_05.py new file mode 100644 index 0000000..28c95a2 --- /dev/null +++ b/2021-python/solutions/day_05.py @@ -0,0 +1,55 @@ +import re +from itertools import chain +from collections import defaultdict +from solutions import BaseSolution + + +class Solution(BaseSolution): + input_file = "05.txt" + + def __str__(self): + return "Day 5: Hydrothermal Venture" + + def parse_input(self, data): + return list( + map( + lambda s: tuple(map(int, re.findall(r"\d+", s))), + data.strip().splitlines(), + ) + ) + + def solve(self, puzzle_input): + hv = list(filter(lambda l: l[0] == l[2] or l[1] == l[3], puzzle_input)) + return self._overlaps(hv) + + def solve_again(self, puzzle_input): + hvd = list( + filter( + lambda l: l[0] == l[2] or l[1] == l[3] or self._diagonal(*l), + puzzle_input, + ) + ) + return self._overlaps(hvd) + + def _overlaps(self, lines): + seen = defaultdict(lambda: 0) + for x1, y1, x2, y2 in lines: + yn = -1 if y1 > y2 else 1 + xn = -1 if x1 > x2 else 1 + if self._diagonal(x1, y1, x2, y2): + pl = abs(y1 - y2) + for n in range(pl + 1): + seen[(y1 + n * yn, x1 + n * xn)] += 1 + else: + for y in range(min(y1, y2), max(y1, y2) + 1): + for x in range(min(x1, x2), max(x1, x2) + 1): + seen[(y, x)] += 1 + return sum(map(lambda v: v > 1, seen.values())) + + def _diagonal(self, x1, y1, x2, y2): + return abs(x1 - x2) == abs(y1 - y2) + + +if __name__ == "__main__": + solution = Solution() + solution.show_results() diff --git a/2021-python/tests/test_day_05.py b/2021-python/tests/test_day_05.py new file mode 100644 index 0000000..cc91d71 --- /dev/null +++ b/2021-python/tests/test_day_05.py @@ -0,0 +1,39 @@ +import unittest + +from solutions.day_05 import Solution + + +class Day05TestCase(unittest.TestCase): + def setUp(self): + self.solution = Solution() + self.puzzle_input = self.solution.parse_input( + """ + 0,9 -> 5,9 +8,0 -> 0,8 +9,4 -> 3,4 +2,2 -> 2,1 +7,0 -> 7,4 +6,4 -> 2,0 +0,9 -> 2,9 +3,4 -> 1,4 +0,0 -> 8,8 +5,5 -> 8,2 + """ + ) + + def test_parse_puzzle_input(self): + data = """ + 11,222 -> 4444,55555 +8,0 -> 0,8 + """ + assert self.solution.parse_input(data) == [(11, 222, 4444, 55555), (8, 0, 0, 8)] + + def test_solve_first_part(self): + assert self.solution.solve(self.puzzle_input) == 5 + + def test_solve_second_part(self): + assert self.solution.solve_again(self.puzzle_input) == 12 + + +if __name__ == "__main__": + unittest.main()