commit f567407457ff31632cd8475b6a414d19ccafcc6f
parent 6d614d6d159f60c4698556c9f413e417973c07a1
Author: Eamon Caddigan <eamon.caddigan@gmail.com>
Date: Fri, 10 Dec 2021 11:39:20 -0500
Added type hints!
Diffstat:
3 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/day10_part1.py b/day10_part1.py
@@ -5,6 +5,7 @@ For part 1, we are finding 'corrupted' lines from the navigation subsystem
# I'm not going to bother trying to use pandas for this one.
+from typing import List
from utils import get_puzzle_input
EXAMPLE_INPUT = \
@@ -20,30 +21,30 @@ EXAMPLE_INPUT = \
<{([{{}}[<[[[<>{}]]]>[]]
"""
-def convert_input_to_list(input_string):
+def convert_input_to_list(input_string: str) -> List[str]:
"""Convert the puzzle input to a list of strings"""
return input_string.rstrip('\n').split('\n')
-def is_open_bracket(bracket):
+def is_open_bracket(bracket: str) -> bool:
"""Returns True iff the character is an open bracket"""
return bracket in '([{<'
-def match_bracket(bracket):
+def match_bracket(bracket: str) -> str:
"""Given an open bracket, return the matching close bracket"""
return {'(': ')', '[': ']', '{': '}', '<': '>'}[bracket]
-def score_bracket(bracket):
+def score_bracket(bracket: str) -> int:
"""Given a close bracket, return its associated score"""
return {')': 3, ']': 57, '}': 1197, '>': 25137}[bracket]
-def score_line(line):
+def score_line(line: str) -> int:
"""Return the 'score' of a corrupted line, or 0 for lines that are not
corrupt"""
# Going with a straightforward solution here: using a stack, pushing open
# brackets and popping when we find close brackets. If we have the wrong
# close bracket, return a score for the bracket we have, otherwise we
# return 0.
- bracket_stack = []
+ bracket_stack: List[str] = []
for bracket in line:
if is_open_bracket(bracket):
bracket_stack.append(bracket)
@@ -52,11 +53,11 @@ def score_line(line):
return score_bracket(bracket)
return 0
-def solve_puzzle(input_string):
+def solve_puzzle(input_string: str) -> int:
"""Return the numeric solution to the puzzle"""
return sum([score_line(l) for l in convert_input_to_list(input_string)])
-def main():
+def main() -> None:
"""Run when the file is called as a script"""
assert solve_puzzle(EXAMPLE_INPUT) == 26397
print("Score for corrupted lines:",
diff --git a/day10_part2.py b/day10_part2.py
@@ -3,17 +3,18 @@
For part 2, we are completing the 'incomplete' lines and finding the score
associated with their completion."""
+from typing import List
from day10_part1 import (EXAMPLE_INPUT,
convert_input_to_list,
is_open_bracket,
match_bracket)
from utils import get_puzzle_input
-def score_bracket(bracket):
+def score_bracket(bracket: str) -> int:
"""Given a close bracket, return its associated score"""
return {')': 1, ']': 2, '}': 3, '>': 4}[bracket]
-def score_line(line):
+def score_line(line: str) -> int:
"""Return the 'score' of an incomplete line, or 0 for lines that are not
incomplete or are corrupt"""
# The problem description text implies that a line must be incomplete or
@@ -21,8 +22,8 @@ def score_line(line):
# I'm going to return a score of 0 for any line that is neither incomplete
# nor corrupt (even though there are none in the example input and probably
# none in my puzzle input). Just using a loop and stack again.
- bracket_stack = []
- line_score = 0
+ bracket_stack: List[str] = []
+ line_score: int = 0
# line_score = line_score * 5 + score_bracket(bracket)
for bracket in line:
if is_open_bracket(bracket):
@@ -43,23 +44,23 @@ def score_line(line):
return line_score
-def filter_zeros(scores):
+def filter_zeros(scores: List[int]) -> List[int]:
"""Remove zeros from the list of scores"""
return [s for s in scores if s != 0]
-def middle_score(scores):
+def middle_score(scores: List[int]) -> int:
"""Sort and return the middle item of the list"""
# I could use `median` from numpy, but since the puzzle prompt promises an
# odd number of lines, it's easy to implement ourselves
return sorted(scores)[len(scores)//2]
-def solve_puzzle(input_string):
+def solve_puzzle(input_string: str) -> int:
"""Return the numeric solution to the puzzle"""
return middle_score(
filter_zeros([score_line(l) for l in convert_input_to_list(input_string)])
)
-def main():
+def main() -> None:
"""Run when the file is called as a script"""
assert solve_puzzle(EXAMPLE_INPUT) == 288957
print("Middle score of incomplete lines:",
diff --git a/utils.py b/utils.py
@@ -1,21 +1,22 @@
"""A collection of utilities that should be useful for more than one puzzle."""
import os.path
+from typing import Any
import requests
import numpy as np
import pandas as pd
-def convert_lines_to_series(input_string):
+def convert_lines_to_series(input_string: str) -> pd.Series:
"""Return a pandas Series consisting of the lines in the
(newline-delimited) input string"""
return pd.Series(input_string.rstrip('\n').split('\n'))
-def convert_int_line_to_series(input_string):
+def convert_int_line_to_series(input_string: str) -> pd.Series:
"""Converts one (optionally newline-terminated) string of comma-separated
integers to a pandas Series"""
return pd.Series(input_string.rstrip().split(',')).astype(np.int64)
-def get_puzzle_input(day_number, binary=False):
+def get_puzzle_input(day_number: int, binary: bool = False) -> Any:
"""Downloads and returns the input data for the puzzle on a given day.
Note: requires a 'session' cookie string to be stored in
'~/.config/advent_of_code/session' and will raise an error if it's not
@@ -23,7 +24,8 @@ def get_puzzle_input(day_number, binary=False):
if binary:
raise RuntimeError('binary file output not supported yet')
- with open(os.path.expanduser('~/.config/advent_of_code/session'), 'rt') \
+ with open(os.path.expanduser('~/.config/advent_of_code/session'),
+ 'rt', encoding='utf8') \
as f_in:
session = f_in.readline().strip()