From 801f977e92317607aa6ab8c8917d4b0066d5adf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Ytterstr=C3=B6m?= Date: Fri, 10 Dec 2021 13:25:56 +0100 Subject: [PATCH] Solve 2021:10 "Syntax Scoring" Spent over an hour trying to figure out the incomplete sequenses, only to realize it was easier to begin from the other way around. After that, solution came out nice and clean. --- 2021-python/solutions/day_10.py | 80 ++++++++++++++++++++++++++++++++ 2021-python/tests/test_day_10.py | 39 ++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 2021-python/solutions/day_10.py create mode 100644 2021-python/tests/test_day_10.py diff --git a/2021-python/solutions/day_10.py b/2021-python/solutions/day_10.py new file mode 100644 index 0000000..0a17b55 --- /dev/null +++ b/2021-python/solutions/day_10.py @@ -0,0 +1,80 @@ +from collections import deque +from solutions import BaseSolution + + +class Solution(BaseSolution): + input_file = "10.txt" + + def __str__(self): + return "Day 10: Syntax Scoring" + + def parse_input(self, data): + return data.split() + + def solve(self, puzzle_input): + scores = { + ")": 3, + "]": 57, + "}": 1197, + ">": 25137, + } + co = {"]": "[", "}": "{", ">": "<", ")": "("} + openers = co.values() + closers = co.keys() + + def corrupt(l): + o = deque() + for i, c in enumerate(l): + if c in openers: + o.append(c) + continue + if co[c] != o.pop(): + return i, c + else: + return 0 + + lines = list(filter(corrupt, puzzle_input)) + return sum(scores[c] for _, c in map(corrupt, lines)) + + def solve_again(self, puzzle_input): + scoremap = { + ")": 1, + "]": 2, + "}": 3, + ">": 4, + } + co = {"]": "[", "}": "{", ">": "<", ")": "("} + oc = dict([(o, c) for c, o in co.items()]) + openers = co.values() + closers = co.keys() + + def score(chars): + s = 0 + for i, x in enumerate(chars): + s *= 5 + s += scoremap[x] + return s + + def incomplete(l): + o = deque() + for c in l: + if c in openers: + o.append(c) + continue + if co[c] != o.pop(): + return 0 + else: + return o + + lines = list(filter(incomplete, puzzle_input)) + med = len(lines) // 2 + completes = [ + score([oc[oo] for oo in reversed(o)]) for o in map(incomplete, lines) + ] + return sorted(completes)[med] + return True + + +if __name__ == "__main__": + solution = Solution() + solution.show_results() diff --git a/2021-python/tests/test_day_10.py b/2021-python/tests/test_day_10.py new file mode 100644 index 0000000..aefb889 --- /dev/null +++ b/2021-python/tests/test_day_10.py @@ -0,0 +1,39 @@ +import unittest + +from solutions.day_10 import Solution + + +class Day10TestCase(unittest.TestCase): + def setUp(self): + self.solution = Solution() + self.puzzle_input = self.solution.parse_input( + """ + [({(<(())[]>[[{[]{<()<>> +[(()[<>])]({[<{<<[]>>( +{([(<{}[<>[]}>{[]{[(<()> +(((({<>}<{<{<>}{[]{[]{} +[[<[([]))<([[{}[[()]]] +[{[{({}]{}}([{[{{{}}([] +{<[[]]>}<{[{[{[]{()[[[] +[<(<(<(<{}))><([]([]() +<{([([[(<>()){}]>(<<{{ +<{([{{}}[<[[[<>{}]]]>[]] + """ + ) + + def test_parse_puzzle_input(self): + data = """ + abc + efg + """ + assert self.solution.parse_input(data) == ["abc", "efg"] + + def test_solve_first_part(self): + assert self.solution.solve(self.puzzle_input) == 26397 + + def test_solve_second_part(self): + assert self.solution.solve_again(self.puzzle_input) == 288957 + + +if __name__ == "__main__": + unittest.main()