diff --git a/py/2017/09/solve.py b/py/2017/09/solve.py deleted file mode 100644 index 3ab1f12..0000000 --- a/py/2017/09/solve.py +++ /dev/null @@ -1,95 +0,0 @@ -import sys - -# PART 1 - -class Stream: - def __init__(self, string): - self.content = list(string) - self.content.reverse() - - def peek(self): - return self.content[-1] - - def pop(self): - return self.content.pop() - -def load_groups(filename): - groups = [] - with open(filename, "r") as f: - for line in f: - stream = Stream(line[:-1]) - group, garbage = parse_group(stream) - groups.append((group, garbage)) - return groups - -def parse_group(stream): - assert stream.pop() == "{" - - if stream.peek() == "}": - assert stream.pop() == "}" - return [], 0 - - groups = [] - garbage = 0 - - while True: - # Determine which sub-parser to use - if stream.peek() == "{": - group, more_garbage = parse_group(stream) - groups.append(group) - garbage += more_garbage - elif stream.peek() == "<": - garbage += parse_garbage(stream) - else: - raise Exception("Incorrectly formatted input") - - # Determine whether to stop parsing - if stream.peek() == "}": - break - elif stream.peek() == ",": - assert stream.pop() == "," - else: - raise Exception("Incorrectly formatted input") - - assert stream.pop() == "}" - return groups, garbage - -def parse_garbage(stream): - assert stream.pop() == "<" - - escaped = False - garbage = 0 - - while True: - if escaped: - stream.pop() - escaped = False - elif stream.peek() == "!": - assert stream.pop() == "!" - escaped = True - elif stream.peek() == ">": - break - else: - stream.pop() - garbage += 1 - - assert stream.pop() == ">" - - return garbage - -def group_score(group, level=1): - return sum(group_score(subgroup, level + 1) for subgroup in group) + level - -# PART 2 - -def main(filename): - print(f"Solutions for {filename}") - groups = load_groups(filename) - for group, garbage in groups: - score = group_score(group) - print(f"Part 1: {score}") - print(f"Part 2: {garbage}") - -if __name__ == "__main__": - for filename in sys.argv[1:]: - main(filename) diff --git a/py/aoc/__init__.py b/py/aoc/__init__.py index bcb62f9..ae32e22 100644 --- a/py/aoc/__init__.py +++ b/py/aoc/__init__.py @@ -2,7 +2,7 @@ import sys import argparse from pathlib import Path -from .y2017 import d01, d02, d03, d04, d05, d06, d07, d08 +from .y2017 import d01, d02, d03, d04, d05, d06, d07, d08, d09 from .y2018 import d01, d02, d03, d04, d05, d06, d07, d08, d09, d10, d11 from .y2020 import d10 from .y2021 import d14 @@ -17,6 +17,7 @@ DAYS = { "2017_06": y2017.d06.solve, "2017_07": y2017.d07.solve, "2017_08": y2017.d08.solve, + "2017_09": y2017.d09.solve, "2018_01": y2018.d01.solve, "2018_02": y2018.d02.solve, "2018_03": y2018.d03.solve, diff --git a/py/aoc/y2017/d09.py b/py/aoc/y2017/d09.py new file mode 100644 index 0000000..d381656 --- /dev/null +++ b/py/aoc/y2017/d09.py @@ -0,0 +1,88 @@ +class Stream: + def __init__(self, string): + self.content = list(string) + self.content.reverse() + + def peek(self): + return self.content[-1] + + def pop(self): + return self.content.pop() + + +def load_groups(inputstr): + groups = [] + for line in inputstr.splitlines(): + stream = Stream(line) + group, garbage = parse_group(stream) + groups.append((group, garbage)) + return groups + + +def parse_group(stream): + assert stream.pop() == "{" + + if stream.peek() == "}": + assert stream.pop() == "}" + return [], 0 + + groups = [] + garbage = 0 + + while True: + # Determine which sub-parser to use + if stream.peek() == "{": + group, more_garbage = parse_group(stream) + groups.append(group) + garbage += more_garbage + elif stream.peek() == "<": + garbage += parse_garbage(stream) + else: + raise Exception("Incorrectly formatted input") + + # Determine whether to stop parsing + if stream.peek() == "}": + break + elif stream.peek() == ",": + assert stream.pop() == "," + else: + raise Exception("Incorrectly formatted input") + + assert stream.pop() == "}" + return groups, garbage + + +def parse_garbage(stream): + assert stream.pop() == "<" + + escaped = False + garbage = 0 + + while True: + if escaped: + stream.pop() + escaped = False + elif stream.peek() == "!": + assert stream.pop() == "!" + escaped = True + elif stream.peek() == ">": + break + else: + stream.pop() + garbage += 1 + + assert stream.pop() == ">" + + return garbage + + +def group_score(group, level=1): + return sum(group_score(subgroup, level + 1) for subgroup in group) + level + + +def solve(inputstr): + groups = load_groups(inputstr) + for group, garbage in groups: + score = group_score(group) + print(f"Part 1: {score}") + print(f"Part 2: {garbage}")