 My attempts to work through the 2021 Advent of Code problems.
Log | Files | Refs | README | LICENSE

```commit 119b6797720051c4aaaf8f6f52ac68ca2f51b7a2
Date:   Sat, 11 Dec 2021 05:42:57 -0500

Solution to day 11, part 2

Diffstat:
```
```1 file changed, 50 insertions(+), 0 deletions(-)
diff --git a/day11_part2.py b/day11_part2.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+"""Advent of Code 2021, day 11 (part 2): Flashing octopuses
+For part 2, we're simulating bioluminescent octopuses again, and this time we
+want to find the `step` at which they all flash simultaneously."""
+
+# I think I can pretty much use everything from part 1 here and just update the
+# solving code
+
+import numpy as np
+from day11_part1 import (EXAMPLE_INPUT,
+                         convert_input_to_array,
+                         simulate_step)
+from utils import get_puzzle_input
+
+def all_flashed(energy_levels: np.ndarray) -> bool:
+    """Detects the moment when all energy levels have been reset to 0"""
+    return not energy_levels.any()
+
+def run_simulation_until_synchronized(energy_levels: np.ndarray) -> int:
+    """Run the simulation from the initial 2d array of energy levels until all
+    octopuses flash at the same time, and return the step number at which it
+    occurred"""
+    # Leaning on Python's nice iterator behavior and for/else syntax: no need
+    # to risk an infinite loop, we can set a "reasonable" limit of iterations
+    # up front. Also I just love underscores in numeric literals.
+    for num_steps in range(1_000_000):
+        energy_levels = simulate_step(energy_levels)
+        if all_flashed(energy_levels):
+            break
+    else:
+        raise RuntimeError("No synchronized flash detected after many steps")
+
+    # We're counting steps from 1 apparently
+    return num_steps + 1
+
+def solve_puzzle(input_string: str) -> int:
+    """Return the numeric solution to the puzzle"""
+    return run_simulation_until_synchronized(
+        convert_input_to_array(input_string)
+    )
+
+def main() -> None:
+    """Run when the file is called as a script"""
+    assert solve_puzzle(EXAMPLE_INPUT) == 195
+    # Is that you, Shevek?
+    print("Number of steps to simultaneity:",
+          solve_puzzle(get_puzzle_input(11)))
+
+if __name__ == "__main__":
+    main()
```