diff --git a/challenges/2021/10-syntaxScoring/README.md b/challenges/2021/10-syntaxScoring/README.md new file mode 100644 index 0000000..4a32b7d --- /dev/null +++ b/challenges/2021/10-syntaxScoring/README.md @@ -0,0 +1,2 @@ +# [Day 10: Syntax Scoring](https://adventofcode.com/2021/day/10) + diff --git a/challenges/2021/10-syntaxScoring/benchmark.json b/challenges/2021/10-syntaxScoring/benchmark.json new file mode 100644 index 0000000..2029846 --- /dev/null +++ b/challenges/2021/10-syntaxScoring/benchmark.json @@ -0,0 +1,15 @@ +{ + "day": 10, + "dir": "challenges/2021/10-syntaxScoring", + "implementations": { + "Python": { + "part.1.avg": 0.0013953149318695068, + "part.1.max": 0.003077268600463867, + "part.1.min": 0.0008635520935058594, + "part.2.avg": 0.0033985512256622316, + "part.2.max": 0.0085296630859375, + "part.2.min": 0.0021257400512695312 + } + }, + "numRuns": 1000 +} \ No newline at end of file diff --git a/challenges/2021/10-syntaxScoring/info.json b/challenges/2021/10-syntaxScoring/info.json new file mode 100644 index 0000000..7185655 --- /dev/null +++ b/challenges/2021/10-syntaxScoring/info.json @@ -0,0 +1,17 @@ +{ + "inputFile": "input.txt", + "testCases": { + "one": [ + { + "input": "[({(<(())[]>[[{[]{<()<>>\n[(()[<>])]({[<{<<[]>>(\n{([(<{}[<>[]}>{[]{[(<()>\n(((({<>}<{<{<>}{[]{[]{}\n[[<[([]))<([[{}[[()]]]\n[{[{({}]{}}([{[{{{}}([]\n{<[[]]>}<{[{[{[]{()[[[]\n[<(<(<(<{}))><([]([]()\n<{([([[(<>()){}]>(<<{{\n<{([{{}}[<[[[<>{}]]]>[]]\n", + "expected": "26397" + } + ], + "two": [ + { + "input": "[({(<(())[]>[[{[]{<()<>>\n[(()[<>])]({[<{<<[]>>(\n{([(<{}[<>[]}>{[]{[(<()>\n(((({<>}<{<{<>}{[]{[]{}\n[[<[([]))<([[{}[[()]]]\n[{[{({}]{}}([{[{{{}}([]\n{<[[]]>}<{[{[{[]{()[[[]\n[<(<(<(<{}))><([]([]()\n<{([([[(<>()){}]>(<<{{\n<{([{{}}[<[[[<>{}]]]>[]]\n", + "expected": "288957" + } + ] + } +} \ No newline at end of file diff --git a/challenges/2021/10-syntaxScoring/py/__init__.py b/challenges/2021/10-syntaxScoring/py/__init__.py new file mode 100644 index 0000000..b706a2a --- /dev/null +++ b/challenges/2021/10-syntaxScoring/py/__init__.py @@ -0,0 +1,120 @@ +from typing import List, Optional, Tuple +from aocpy import BaseChallenge +from dataclasses import dataclass +import math + + +CHECKER_POINTS = { + ")": 3, + "]": 57, + "}": 1197, + ">": 25137, +} + +AC_POINTS = { + ")": 1, + "]": 2, + "}": 3, + ">": 4, +} + + +@dataclass +class Chunk: + text: str + + def is_corrupted(self) -> Tuple[bool, Optional[str]]: + stack = [] + for char in self.text: + + if char == "(": + stack.append(")") + elif char == "[": + stack.append("]") + elif char == "{": + stack.append("}") + elif char == "<": + stack.append(">") + elif char == ")" or char == "]" or char == "}" or char == ">": + r = stack.pop() + if r != char: + return True, char + else: + raise ValueError(f"unknown character in chunk string ({char=})") + + return False, None + + def complete(self) -> str: + stack = [] + output = "" + + n = 0 + while True: + + char = None + if n < len(self.text): + char = self.text[n] + + if len(stack) == 0 and char is None: + break + + if char is None: + output += stack.pop() + elif char == "(": + stack.append(")") + elif char == "[": + stack.append("]") + elif char == "{": + stack.append("}") + elif char == "<": + stack.append(">") + elif char == ")" or char == "]" or char == "}" or char == ">": + r = stack.pop() + if r != char: + raise ValueError(f"cannot correct corrupted chunk (wanted {r}, got {char})") + else: + raise ValueError(f"unknown character in chunk string ({char=})") + + n += 1 + + return output + + +def parse(instr: str) -> List[Chunk]: + return [Chunk(x) for x in instr.strip().splitlines()] + + +class Challenge(BaseChallenge): + + @staticmethod + def one(instr: str) -> int: + chunks = parse(instr) + score = 0 + for chunk in chunks: + is_corrupted, illegal_character = chunk.is_corrupted() + if is_corrupted: + score += CHECKER_POINTS[illegal_character] + return score + + @staticmethod + def two(instr: str) -> int: + chunks = parse(instr) + + def f(x): + y, _ = x.is_corrupted() + return not y + + chunks = list(filter(f, chunks)) + points = [] + for chunk in chunks: + extra = chunk.complete() + n = 0 + for char in extra: + n *= 5 + n += AC_POINTS[char] + points.append(n) + + points = list(sorted(points)) + median = points[math.floor(len(points)/2)] + + return median diff --git a/challenges/2021/README.md b/challenges/2021/README.md index 5903870..451a6a4 100644 --- a/challenges/2021/README.md +++ b/challenges/2021/README.md @@ -18,7 +18,8 @@ Solutions to the [2021 Advent of Code](https://adventofcode.com/2021). | 06 - Lanternfish | Complete | [Python](06-lanternfish/py) | At this rate, the mass of the fish would surpass that of the Earth pretty quickly. | | 07 - The Treachery of Whales | Complete | [Python](07-theTreacheryOfWhales/py) | I'm not 100% sure my solution for part two is valid for all possible inputs. | | 08 - Seven Segment Search | Complete | [Python](08-sevenSegmentSearch/py), [Go](08-sevenSegmentSearch) | I may have taken the easy way out for part two, but it does work! No-one ever said the smart solution is the best solution, anyway. | -| 09 - Smoke Basin * | Complete | [Python](09-smokeBasin/py) | Schmokey! Also, as it turns out, I struggle to implement basic logic. Fun. | +| 09 - Smoke Basin \* | Complete | [Python](09-smokeBasin/py) | Schmokey! Also, as it turns out, I struggle to implement basic logic. Fun. | +| 10 - Syntax Scoring | Complete | [Python](10-syntaxScoring/py) | I can't say I've ever broken something so thoroughly that it has a syntax error on *every* line... | diff --git a/challenges/2021/running-times.png b/challenges/2021/running-times.png index 2dd115e..784194c 100644 Binary files a/challenges/2021/running-times.png and b/challenges/2021/running-times.png differ