My attempts to work through the 2021 Advent of Code problems.

```commit 3e71fb97cb190e8e87d43adbcde6dc8bb342b1d5
Date:   Thu,  9 Dec 2021 10:50:43 -0500

Solution to day 9, part 1

Diffstat:
```
```1 file changed, 51 insertions(+), 0 deletions(-)
diff --git a/day09_part1.py b/day09_part1.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+"""Advent of Code 2021, day 9 (part 1): find the low points of a 2D heightmap"""
+
+# Ok so I've been really twisting my problems into things that can be solved
+# with pandas, but this one really makes the most sense in numpy... and I
+# haven't actually used numpy (by itself) that much this AoC. I also suspect
+# that part 2 might involve convolutions, but I've been wrong before.
+
+import numpy as np
+from utils import get_puzzle_input
+
+EXAMPLE_INPUT = \
+"""2199943210
+3987894921
+9856789892
+8767896789
+9899965678
+"""
+
+def convert_input_to_array(input_string):
+    """Convert the input into an array"""
+    return (
+        np.array([list(line) for line in input_string.rstrip('\n').split('\n')])
+        .astype(int)
+    )
+
+def find_low_points(heightmap):
+    """Return a 2d boolean array of local minima"""
+    return (np.diff(heightmap, axis=0, prepend=10) < 0) & \
+        np.flip(np.diff(np.flip(heightmap, axis=0), axis=0, prepend=10) < 0,
+                axis=0) & \
+        (np.diff(heightmap, axis=1, prepend=10) < 0) & \
+        np.flip(np.diff(np.flip(heightmap, axis=1), axis=1, prepend=10) < 0,
+                axis=1)
+
+def calculate_risk_level(heightmap):
+    """Given a heighmap, find the low points and calculate the risk level"""
+    return sum(heightmap[find_low_points(heightmap)] + 1)
+
+def solve_puzzle(input_string):
+    """Return the numeric solution to the puzzle"""
+    return calculate_risk_level(convert_input_to_array(input_string))
+
+def main():
+    """Run when the file is called as a script"""
+    assert solve_puzzle(EXAMPLE_INPUT) == 15
+    print("Risk level of heightmap:",
+          solve_puzzle(get_puzzle_input(9)))
+
+if __name__ == "__main__":
+    main()
```