From e257eb53359927c537d2e9c31ca8eae7a0f6dfe7 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Thu, 2 Dec 2021 13:58:09 +0100 Subject: Combine parts 1 and 2 into one file --- 2020/19/.gitignore | 1 + 2020/19/Makefile | 8 +++++ 2020/19/puzzle-1.py | 59 ----------------------------------- 2020/19/puzzle-2.py | 84 -------------------------------------------------- 2020/19/puzzles.py | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 143 deletions(-) create mode 100644 2020/19/.gitignore create mode 100644 2020/19/Makefile delete mode 100755 2020/19/puzzle-1.py delete mode 100755 2020/19/puzzle-2.py create mode 100644 2020/19/puzzles.py diff --git a/2020/19/.gitignore b/2020/19/.gitignore new file mode 100644 index 0000000..ffc46fe --- /dev/null +++ b/2020/19/.gitignore @@ -0,0 +1 @@ +puzzle-[12].py diff --git a/2020/19/Makefile b/2020/19/Makefile new file mode 100644 index 0000000..247194a --- /dev/null +++ b/2020/19/Makefile @@ -0,0 +1,8 @@ +all: + sed '/START PART 2/,/END PART 2/d' puzzles.py >puzzle-1.py + sed '/START PART 1/,/END PART 1/d' puzzles.py >puzzle-2.py + chmod +x puzzle-[12].py + +.PHONY: clean +clean: + rm -f puzzle-[12].py diff --git a/2020/19/puzzle-1.py b/2020/19/puzzle-1.py deleted file mode 100755 index 8ca7eb2..0000000 --- a/2020/19/puzzle-1.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python3 - -from collections import OrderedDict - - -def main() -> None: - with open("input", "r") as f: - data = f.readlines() - - i = 0 - rules: list[tuple[str]] = [] - while data[i] != "\n": - rules.append(tuple(x for x in tuple(data[i].split(": ")))) - i += 1 - - tests: list[str] = [] - for line in data: - tests.append(line.strip()) - - patterns: dict[str, list[str]] = {} - - # Get "a" and "b" out of the way to do less comparisons in the next loop. Also make use of - # this loop to strip newlines off of all the rules. - for rule in rules: - rules[rules.index(rule)] = (rule[0], rule[1].strip()) - if len(rule[1]) == 4: - patterns[rule[0]] = [rule[1][1]] - - while len(patterns) != len(rules): - for rule in rules: - if rule[0] in patterns: - continue - - res = rule[1].split(" | ") - req_rules = list(OrderedDict.fromkeys(" ".join(res).split(" "))) - all_in = True - for req in req_rules: - if req not in patterns: - all_in = False - break - if all_in == True: - all_combos: list[str] = [] - for re in res: - re = re.split(" ") - if len(re) == 1: - all_combos.extend(patterns[re[0]]) - else: - for x in patterns[re[0]]: - for y in patterns[re[1]]: - all_combos.append(f"{x}{y}") - all_combos = list(OrderedDict.fromkeys(all_combos)) - - patterns[rule[0]] = all_combos - - print(len([test for test in tests if test in patterns["0"]])) - - -if __name__ == "__main__": - main() diff --git a/2020/19/puzzle-2.py b/2020/19/puzzle-2.py deleted file mode 100755 index b0efe15..0000000 --- a/2020/19/puzzle-2.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python3 - -from collections import OrderedDict -from re import search - - -def check(test: str, patterns: dict[str, list[str]]) -> bool: - chunks = string_divide(test, 8) - search_str = "" - - for chunk in chunks: - if chunk in patterns["42"]: - search_str += "0" - elif chunk in patterns["31"]: - search_str += "1" - else: - return False - - # 42 = 0, 31 = 1 - res = search(r"^(0)+(1)+$", search_str) - return not (not res or search_str.count("0") <= search_str.count("1")) - - -def string_divide(string: str, div: int) -> list[str]: - l: list[str] = [] - for i in range(0, len(string), div): - l.append(string[i : i + div]) - return l - - -def main() -> None: - with open("input", "r") as f: - data = f.readlines() - - i = 0 - rules: list[tuple[str]] = [] - while data[i] != "\n": - rules.append(tuple(x for x in tuple(data[i].split(": ")))) - i += 1 - - tests: list[str] = [] - for line in data: - tests.append(line.strip()) - - patterns: dict[str, list[str]] = {} - - # Get "a" and "b" out of the way to do less comparisons in the next loop. Also make use of - # this loop to strip newlines off of all the rules. - for rule in rules: - rules[rules.index(rule)] = (rule[0], rule[1].strip()) - if len(rule[1]) == 4: - patterns[rule[0]] = [rule[1][1]] - - while len(patterns) != len(rules): - for rule in rules: - if rule[0] in patterns: - continue - - res = rule[1].split(" | ") - req_rules = list(OrderedDict.fromkeys(" ".join(res).split(" "))) - all_in = True - for req in req_rules: - if req not in patterns: - all_in = False - break - if all_in == True: - all_combos: list[str] = [] - for re in res: - re = re.split(" ") - if len(re) == 1: - all_combos.extend(patterns[re[0]]) - else: - for x in patterns[re[0]]: - for y in patterns[re[1]]: - all_combos.append(f"{x}{y}") - all_combos = list(OrderedDict.fromkeys(all_combos)) - - patterns[rule[0]] = all_combos - - print(len([test for test in tests if check(test, patterns)])) - - -if __name__ == "__main__": - main() diff --git a/2020/19/puzzles.py b/2020/19/puzzles.py new file mode 100644 index 0000000..f2a4bcf --- /dev/null +++ b/2020/19/puzzles.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 + +from collections import OrderedDict +from itertools import product + +# START PART 2 +from re import search + + +def check(test: str, patterns: dict[str, list[str]]) -> bool: + chunks = string_divide(test, 8) + search_str = "" + + for chunk in chunks: + if chunk in patterns["42"]: + search_str += "0" + elif chunk in patterns["31"]: + search_str += "1" + else: + return False + + # 42 = 0, 31 = 1 + res = search(r"^(0)+(1)+$", search_str) + return not (not res or search_str.count("0") <= search_str.count("1")) + + +def string_divide(string: str, div: int) -> list[str]: + l: list[str] = [] + for i in range(0, len(string), div): + l.append(string[i : i + div]) + return l + + +# END PART 2 + + +def main() -> None: + with open("input", "r", encoding="utf-8") as f: + data = f.readlines() + + i = 0 + rules: list[tuple[str]] = [] + while data[i] != "\n": + rules.append(tuple(x for x in tuple(data[i].split(": ")))) + i += 1 + + tests = [line.strip() for line in data] + patterns: dict[str, list[str]] = {} + + # Get "a" and "b" out of the way to do less comparisons in the next loop. Also make use of + # this loop to strip newlines off of all the rules. + for rule in rules: + rules[rules.index(rule)] = (rule[0], rule[1].strip()) + if len(rule[1]) == 4: + patterns[rule[0]] = [rule[1][1]] + + while len(patterns) != len(rules): + for rule in rules: + if rule[0] in patterns: + continue + + res = rule[1].split(" | ") + if all(req in patterns for req in list(OrderedDict.fromkeys(" ".join(res).split(" ")))): + all_combos: list[str] = [] + for re in res: + re = re.split(" ") + if len(re) == 1: + all_combos.extend(patterns[re[0]]) + else: + all_combos = list( + OrderedDict.fromkeys( + all_combos + + [f"{x}{y}" for x, y in product(patterns[re[0]], patterns[re[1]])] + ) + ) + + patterns[rule[0]] = all_combos + + # START PART 1 + print(len([test for test in tests if test in patterns["0"]])) + # END PART 1 START PART 2 + print(len([test for test in tests if check(test, patterns)])) + + +# END PART 2 + + +if __name__ == "__main__": + main() -- cgit v1.2.3