From f0510ee0dc161749ad8d5494d4af1e4f2338387f Mon Sep 17 00:00:00 2001 From: Jonathan Tsai Date: Wed, 7 Dec 2022 20:23:37 -0800 Subject: [PATCH] cleanup AoC 2015.12 solutions #1-9 --- adventofcode/2015/01.py | 24 ++++----- adventofcode/2015/02.py | 39 +++++++------- adventofcode/2015/03.py | 24 ++++----- adventofcode/2015/04.py | 28 ++++------ adventofcode/2015/05.py | 45 +++++++--------- adventofcode/2015/06.py | 52 +++++++++--------- adventofcode/2015/06.test.in | 2 - adventofcode/2015/07.py | 101 ++++++++++++++++------------------- adventofcode/2015/08.py | 27 ++++------ adventofcode/2015/09.py | 54 +++++++++---------- adventofcode/utils/config.py | 4 +- 11 files changed, 180 insertions(+), 220 deletions(-) diff --git a/adventofcode/2015/01.py b/adventofcode/2015/01.py index 5646238..50301cb 100644 --- a/adventofcode/2015/01.py +++ b/adventofcode/2015/01.py @@ -1,24 +1,20 @@ from utils import ( - InputConfig, - ingest, + BaseSolution, + config, + main, + solution, ) -INPUT_FILE = '01.in' -EXPECTED_ANSWERS = (74, 1795, ) +config.EXPECTED_ANSWERS = (74, 1795) +config.INPUT_CONFIG.as_oneline = True -def main(): - solution = Solution() - answers = (solution.solve1(), solution.solve2(), ) - print(answers) - assert(answers == EXPECTED_ANSWERS) - -class Solution: - def __init__(self): - data = ingest(INPUT_FILE, InputConfig(as_oneline=True)) - self.instructions = data +@solution +class Solution(BaseSolution): + def process_data(self): + self.instructions = self.data def solve1(self): floor = 0 diff --git a/adventofcode/2015/02.py b/adventofcode/2015/02.py index 395a213..4eef2ae 100644 --- a/adventofcode/2015/02.py +++ b/adventofcode/2015/02.py @@ -1,20 +1,17 @@ -from utils import ingest +from utils import ( + BaseSolution, + config, + main, + solution, +) -INPUT_FILE = '02.in' -EXPECTED_ANSWERS = (1588178, 3783758, ) +config.EXPECTED_ANSWERS = (1588178, 3783758) -def main(): - solution = Solution() - answers = (solution.solve1(), solution.solve2(), ) - print(answers) - assert(answers == EXPECTED_ANSWERS) - - -class Solution: - def __init__(self): - self.data = ingest(INPUT_FILE) +@solution +class Solution(BaseSolution): + def process_data(self): self.presents = [Present(dimensions) for dimensions in self.data] def solve1(self): @@ -33,7 +30,7 @@ def __init__(self, dimensions): @property def surface_area(self): l, w, h = self.l, self.w, self.h - area = 2*l*w + 2*w*h + 2*h*l + area = 2 * l * w + 2 * w * h + 2 * h * l return area @property @@ -50,11 +47,13 @@ def lh_area(self): @property def smallest_side_area(self): - return min([ - self.lw_area, - self.wh_area, - self.lh_area, - ]) + return min( + [ + self.lw_area, + self.wh_area, + self.lh_area, + ] + ) @property def wrapping_paper_area(self): @@ -63,7 +62,7 @@ def wrapping_paper_area(self): @property def smallest_perimeter(self): a, b, c = sorted([self.l, self.w, self.h]) - return 2*a + 2*b + return 2 * a + 2 * b @property def volume(self): diff --git a/adventofcode/2015/03.py b/adventofcode/2015/03.py index 3d2e0f9..355bb91 100644 --- a/adventofcode/2015/03.py +++ b/adventofcode/2015/03.py @@ -2,26 +2,22 @@ from collections import defaultdict from utils import ( - InputConfig, - ingest, + BaseSolution, + config, + main, + solution, ) -INPUT_FILE = '03.in' -EXPECTED_ANSWERS = (2565, 2639, ) +config.EXPECTED_ANSWERS = (2565, 2639) +config.INPUT_CONFIG.as_oneline = True -def main(): - solution = Solution() - answers = (solution.solve1(), solution.solve2(), ) - print(answers) - assert(answers == EXPECTED_ANSWERS) - -class Solution: - def __init__(self): - data = ingest(INPUT_FILE, InputConfig(as_oneline=True)) - self.directions = data +@solution +class Solution(BaseSolution): + def process_data(self): + self.directions = self.data self.delivery_map = DeliveryMap(self.directions) def solve1(self): diff --git a/adventofcode/2015/04.py b/adventofcode/2015/04.py index da3d666..8ce96dc 100644 --- a/adventofcode/2015/04.py +++ b/adventofcode/2015/04.py @@ -2,29 +2,23 @@ import hashlib from utils import ( - InputConfig, - ingest, + BaseSolution, + config, + main, + solution, ) -INPUT_FILE = '04.in' -EXPECTED_ANSWERS = (254575, 1038736, ) +config.EXPECTED_ANSWERS = (254575, 1038736) +config.TEST_CASES = {'': (609043, 6742839)} -# INPUT_FILE = '4.test.in' -# EXPECTED_ANSWERS = (609043, 6742839, ) +config.INPUT_CONFIG.as_oneline = True -def main(): - solution = Solution() - answers = (solution.solve1(), solution.solve2(), ) - print(answers) - assert(answers == EXPECTED_ANSWERS) - - -class Solution: - def __init__(self): - data = ingest(INPUT_FILE, InputConfig(as_oneline=True)) - self.key = data +@solution +class Solution(BaseSolution): + def process_data(self): + self.key = self.data def solve1(self): n = 1 diff --git a/adventofcode/2015/05.py b/adventofcode/2015/05.py index db31587..0fd42fc 100644 --- a/adventofcode/2015/05.py +++ b/adventofcode/2015/05.py @@ -1,23 +1,20 @@ -from utils import ingest +from utils import ( + BaseSolution, + config, + main, + solution, +) -INPUT_FILE = '05.in' -EXPECTED_ANSWERS = (255, 55, ) +config.EXPECTED_ANSWERS = (255, 55) +config.TEST_CASES = { + '': (2, 2), +} -# INPUT_FILE = '05.test.in' -# EXPECTED_ANSWERS = (2, 2, ) - -def main(): - solution = Solution() - answers = (solution.solve1(), solution.solve2(), ) - print(answers) - assert(answers == EXPECTED_ANSWERS) - - -class Solution: - def __init__(self): - self.data = ingest(INPUT_FILE) +@solution +class Solution(BaseSolution): + def process_data(self): self.strings = [NaughtyOrNice(s) for s in self.data] def solve1(self): @@ -53,10 +50,7 @@ def contains_naughty(self): @property def contains_3_vowels(self): - vowels = [ - c for c in self.s - if c in self.VOWELS - ] + vowels = [c for c in self.s if c in self.VOWELS] has_3 = len(vowels) >= 3 return has_3 @@ -88,9 +82,9 @@ def has_distinct_repeating_pair(self): has_repeat = False for i in range(len(s) - 4 + 1): - pair = s[i:i + 2] - for j in range(i+2, len(s) - 2 + 1): - pair2 = s[j:j + 2] + pair = s[i : i + 2] + for j in range(i + 2, len(s) - 2 + 1): + pair2 = s[j : j + 2] if pair == pair2: has_repeat = True break @@ -115,10 +109,7 @@ def has_3_palindrome(self): @property def is_nice2(self): - is_nice = ( - self.has_distinct_repeating_pair - and self.has_3_palindrome - ) + is_nice = self.has_distinct_repeating_pair and self.has_3_palindrome return is_nice diff --git a/adventofcode/2015/06.py b/adventofcode/2015/06.py index 8f0a928..066408f 100644 --- a/adventofcode/2015/06.py +++ b/adventofcode/2015/06.py @@ -1,26 +1,24 @@ # Python Standard Library Imports import re -from utils import ingest +from utils import ( + BaseSolution, + config, + main, + solution, +) -INPUT_FILE = '06.in' -EXPECTED_ANSWERS = (543903, 14687245, ) +config.EXPECTED_ANSWERS = (543903, 14687245) +config.TEST_CASES = { + '': (1_000_000 - 1_000 - 4, 3001997), +} -# INPUT_FILE = '06.test.in' -# EXPECTED_ANSWERS = (1000000 - (1000000 - 1000 - 4), 3001997, ) - -def main(): - solution = Solution() - answers = (solution.solve1(), solution.solve2(), ) - print(answers) - assert(answers == EXPECTED_ANSWERS) - - -class Solution: - def __init__(self): - data = ingest(INPUT_FILE) +@solution +class Solution(BaseSolution): + def process_data(self): + data = self.data self.instructions = [Instruction(instruction) for instruction in data] self.light_show = LightShow(self.instructions) @@ -36,7 +34,9 @@ def solve2(self): class Instruction: - REGEXP = re.compile(r'^(?P(turn on)|(turn off)|(toggle)) (?P\d+),(?P\d+) through (?P\d+),(?P\d+)$') + REGEXP = re.compile( + r'^(?P(turn on)|(turn off)|(toggle)) (?P\d+),(?P\d+) through (?P\d+),(?P\d+)$' + ) def __init__(self, instruction): self.instruction = instruction @@ -57,15 +57,19 @@ def __init__(self, instructions): self.instructions = instructions self.lights = [ - [False, ] * 1000 - for x - in range(1000) + [ + False, + ] + * 1000 + for x in range(1000) ] self.lights2 = [ - [0, ] * 1000 - for x - in range(1000) + [ + 0, + ] + * 1000 + for x in range(1000) ] def run(self): @@ -86,7 +90,7 @@ def run(self): elif operation == 'turn off': lights[i][j] = False elif operation == 'toggle': - lights[i][j] = not(lights[i][j]) + lights[i][j] = not (lights[i][j]) else: raise Exception('Illegal operation: %s' % operation) diff --git a/adventofcode/2015/06.test.in b/adventofcode/2015/06.test.in index 5216830..4506a12 100644 --- a/adventofcode/2015/06.test.in +++ b/adventofcode/2015/06.test.in @@ -1,5 +1,3 @@ turn on 0,0 through 999,999 toggle 0,0 through 999,0 turn off 499,499 through 500,500 -turn on 0,0 through 0,0 -toggle 0,0 through 999,999 diff --git a/adventofcode/2015/07.py b/adventofcode/2015/07.py index 9499fbf..a2743d6 100644 --- a/adventofcode/2015/07.py +++ b/adventofcode/2015/07.py @@ -2,26 +2,23 @@ import re from utils import ( - Re, - ingest, + RE, + BaseSolution, + config, + main, + solution, ) -INPUT_FILE = '07.in' -EXPECTED_ANSWERS = (46065, 14134, ) +config.EXPECTED_ANSWERS = (46065, 14134) -def main(): - solution = Solution() - answers = (solution.solve1(), solution.solve2(), ) - print(answers) - assert(answers == EXPECTED_ANSWERS) - - -class Solution: - def __init__(self): - self.data = ingest(INPUT_FILE) - self.instructions = [Instruction(instruction) for instruction in self.data] +@solution +class Solution(BaseSolution): + def process_data(self): + self.instructions = [ + Instruction(instruction) for instruction in self.data + ] def solve1(self): logic_gates = LogicGates(self.instructions) @@ -42,74 +39,68 @@ def solve2(self): class Instruction: SIGNAL_REGEXP = re.compile(r'^(?P(\d+)|([a-z]+)) -> (?P[a-z]+)$') - AND_REGEXP = re.compile(r'^(?P(\d+)|([a-z]+)) AND (?P(\d+)|([a-z]+)) -> (?P[a-z]+)$') - OR_REGEXP = re.compile(r'^(?P(\d+)|([a-z]+)) OR (?P(\d+)|([a-z]+)) -> (?P[a-z]+)$') - LSHIFT_REGEXP = re.compile(r'^(?P[a-z]+) LSHIFT (?P\d+) -> (?P[a-z]+)$') - RSHIFT_REGEXP = re.compile(r'^(?P[a-z]+) RSHIFT (?P\d+) -> (?P[a-z]+)$') + AND_REGEXP = re.compile( + r'^(?P(\d+)|([a-z]+)) AND (?P(\d+)|([a-z]+)) -> (?P[a-z]+)$' + ) + OR_REGEXP = re.compile( + r'^(?P(\d+)|([a-z]+)) OR (?P(\d+)|([a-z]+)) -> (?P[a-z]+)$' + ) + LSHIFT_REGEXP = re.compile( + r'^(?P[a-z]+) LSHIFT (?P\d+) -> (?P[a-z]+)$' + ) + RSHIFT_REGEXP = re.compile( + r'^(?P[a-z]+) RSHIFT (?P\d+) -> (?P[a-z]+)$' + ) NOT_REGEXP = re.compile(r'^NOT (?P[a-z]+) -> (?P[a-z]+)$') def __init__(self, instruction): self.instruction = instruction - regex = Re() - - if regex.match(self.SIGNAL_REGEXP, instruction): - m = regex.last_match - + if RE.match(self.SIGNAL_REGEXP, instruction): self.instruction_type = 'SIGNAL' self.w, self.wire = ( - m.group('w'), - m.group('wire'), + RE.m.group('w'), + RE.m.group('wire'), ) - elif regex.match(self.AND_REGEXP, instruction): - m = regex.last_match - + elif RE.match(self.AND_REGEXP, instruction): self.instruction_type = 'AND' self.w1, self.w2, self.wire = ( - m.group('w1'), - m.group('w2'), - m.group('wire'), + RE.m.group('w1'), + RE.m.group('w2'), + RE.m.group('wire'), ) - elif regex.match(self.OR_REGEXP, instruction): - m = regex.last_match - + elif RE.match(self.OR_REGEXP, instruction): self.instruction_type = 'OR' self.w1, self.w2, self.wire = ( - m.group('w1'), - m.group('w2'), - m.group('wire'), + RE.m.group('w1'), + RE.m.group('w2'), + RE.m.group('wire'), ) - elif regex.match(self.LSHIFT_REGEXP, instruction): - m = regex.last_match - + elif RE.match(self.LSHIFT_REGEXP, instruction): self.instruction_type = 'LSHIFT' self.w, self.value, self.wire = ( - m.group('w'), - int(m.group('value')), - m.group('wire'), + RE.m.group('w'), + int(RE.m.group('value')), + RE.m.group('wire'), ) - elif regex.match(self.RSHIFT_REGEXP, instruction): - m = regex.last_match - + elif RE.match(self.RSHIFT_REGEXP, instruction): self.instruction_type = 'RSHIFT' self.w, self.value, self.wire = ( - m.group('w'), - int(m.group('value')), - m.group('wire'), + RE.m.group('w'), + int(RE.m.group('value')), + RE.m.group('wire'), ) - elif regex.match(self.NOT_REGEXP, instruction): - m = regex.last_match - + elif RE.match(self.NOT_REGEXP, instruction): self.instruction_type = 'NOT' self.w, self.wire = ( - m.group('w'), - m.group('wire'), + RE.m.group('w'), + RE.m.group('wire'), ) else: raise Exception('Bad instruction: %s' % instruction) diff --git a/adventofcode/2015/08.py b/adventofcode/2015/08.py index 878533a..2cc50b6 100644 --- a/adventofcode/2015/08.py +++ b/adventofcode/2015/08.py @@ -1,23 +1,18 @@ -from utils import ingest +from utils import ( + BaseSolution, + config, + main, + solution, +) -INPUT_FILE = '08.in' -EXPECTED_ANSWERS = (1350, 2085, ) +config.EXPECTED_ANSWERS = (1350, 2085) +config.TEST_CASES = {'': (12, 19)} -# INPUT_FILE = '08.test.in' -# EXPECTED_ANSWERS = (12, 19, ) - -def main(): - solution = Solution() - answers = (solution.solve1(), solution.solve2(), ) - print(answers) - assert(answers == EXPECTED_ANSWERS) - - -class Solution: - def __init__(self): - self.data = ingest(INPUT_FILE) +@solution +class Solution(BaseSolution): + def process_data(self): self.strings = [S(s) for s in self.data] def solve1(self): diff --git a/adventofcode/2015/09.py b/adventofcode/2015/09.py index bbcc391..b1b6213 100644 --- a/adventofcode/2015/09.py +++ b/adventofcode/2015/09.py @@ -3,28 +3,23 @@ from itertools import permutations from utils import ( - Re, - ingest, + RE, + BaseSolution, + config, + main, + solution, ) -INPUT_FILE = '09.in' -EXPECTED_ANSWERS = (117, 909, ) +config.EXPECTED_ANSWERS = (117, 909) +config.TEST_CASES = { + '': (605, 982), +} -# INPUT_FILE = '09.test.in' -# EXPECTED_ANSWERS = (605, 982, ) - -def main(): - solution = Solution() - answers = (solution.solve1(), solution.solve2(), ) - print(answers) - assert(answers == EXPECTED_ANSWERS) - - -class Solution: - def __init__(self): - self.data = ingest(INPUT_FILE) +@solution +class Solution(BaseSolution): + def process_data(self): routes = self.data self.graph = Graph(routes) @@ -40,19 +35,19 @@ def solve2(self): class Graph: - ROUTE_REGEXP = re.compile(r'^(?P[A-Za-z]+) to (?P[A-Za-z]+) = (?P\d+)$') + ROUTE_REGEXP = re.compile( + r'^(?P[A-Za-z]+) to (?P[A-Za-z]+) = (?P\d+)$' + ) def __init__(self, routes): self.nodes = {} - regex = Re() for route in routes: - if regex.match(self.ROUTE_REGEXP, route): - m = regex.last_match + if RE.match(self.ROUTE_REGEXP, route): origin_name, destination_name, weight = ( - m.group('origin'), - m.group('destination'), - int(m.group('weight')), + RE.m.group('origin'), + RE.m.group('destination'), + int(RE.m.group('weight')), ) origin = self.get_node(origin_name) destination = self.get_node(destination_name) @@ -90,7 +85,9 @@ def _tsp_exhaustive(self): for itinerary in p: weight = self.tour(itinerary) - if weight is not None and (best_weight is None or weight < best_weight): + if weight is not None and ( + best_weight is None or weight < best_weight + ): best_itinerary = itinerary best_weight = weight @@ -104,15 +101,16 @@ def longest_itinerary(self): for itinerary in p: weight = self.tour(itinerary) - if weight is not None and (worst_weight is None or weight > worst_weight): + if weight is not None and ( + worst_weight is None or weight > worst_weight + ): worst_itinerary = itinerary worst_weight = weight return worst_weight, worst_itinerary def tour(self, itinerary): - """Returns the total weight for visiting each node in order of `itinerary` - """ + """Returns the total weight for visiting each node in order of `itinerary`""" cost = 0 prev = None diff --git a/adventofcode/utils/config.py b/adventofcode/utils/config.py index 454f7bb..fa536a7 100644 --- a/adventofcode/utils/config.py +++ b/adventofcode/utils/config.py @@ -10,7 +10,7 @@ EXPECTED_ANSWERS = (None, None) TEST_CASES = { - '': (None, None), + # '': (None, None), # 'b': (None, None), # 'c': (None, None), } @@ -31,8 +31,6 @@ DAY = int(PROBLEM_NUM) YEAR = int(solution_filepath.parent.name) -print(PROBLEM_NUM, DAY, YEAR) - # end Automatic inference of PROBLEM_NUM | DAY | YEAR ##################################################