"""
|
|
Advent of Code 2021 - Day 01
|
|
|
|
Run with:
|
|
python puzzles/day01.py inputs/day01.txt
|
|
"""
|
|
import pathlib
|
|
import sys
|
|
from typing import Dict, List, Tuple
|
|
|
|
from numpy import sum as np_sum
|
|
from numpy.lib.stride_tricks import sliding_window_view
|
|
|
|
|
|
def compare(inputs: List[int]) -> Dict[str, int]:
|
|
result = {"increased": 0, "decreased": 0, "no change": 0, "n/a": 0}
|
|
prev = None
|
|
for cur in inputs:
|
|
status = "no change"
|
|
if prev is None:
|
|
status = "n/a"
|
|
elif cur > prev:
|
|
status = "increased"
|
|
elif cur < prev:
|
|
status = "decreased"
|
|
result[status] += 1
|
|
prev = cur
|
|
return result
|
|
|
|
|
|
def part1(inputs: List[int]) -> int:
|
|
"""
|
|
Count the number of times a depth measurement increases from the previous measurement. (There is no measurement before the first measurement.) In the example above, the changes are as follows:
|
|
|
|
199 (N/A - no previous measurement)
|
|
200 (increased)
|
|
208 (increased)
|
|
210 (increased)
|
|
200 (decreased)
|
|
207 (increased)
|
|
240 (increased)
|
|
269 (increased)
|
|
260 (decreased)
|
|
263 (increased)
|
|
|
|
In this example, there are 7 measurements that are larger than the previous measurement.
|
|
"""
|
|
return compare(inputs).get("increased", 0)
|
|
|
|
|
|
def part2(inputs: List[int]) -> int:
|
|
"""
|
|
Start by comparing the first and second three-measurement windows. The measurements in the first window are marked A (199, 200, 208); their sum is 199 + 200 + 208 = 607. The second window is marked B (200, 208, 210); its sum is 618. The sum of measurements in the second window is larger than the sum of the first, so this first comparison increased.
|
|
|
|
Your goal now is to count the number of times the sum of measurements in this sliding window increases from the previous sum. So, compare A with B, then compare B with C, then C with D, and so on. Stop when there aren't enough measurements left to create a new three-measurement sum.
|
|
|
|
In the above example, the sum of each three-measurement window is as follows:
|
|
|
|
A: 607 (N/A - no previous sum)
|
|
B: 618 (increased)
|
|
C: 618 (no change)
|
|
D: 617 (decreased)
|
|
E: 647 (increased)
|
|
F: 716 (increased)
|
|
G: 769 (increased)
|
|
H: 792 (increased)
|
|
|
|
In this example, there are 5 sums that are larger than the previous sum
|
|
"""
|
|
inputs = np_sum(sliding_window_view(inputs, window_shape=3), axis=1)
|
|
return compare(inputs).get("increased", 0)
|
|
|
|
|
|
def parse(inputs: str) -> List[int]:
|
|
"""Parse the input string"""
|
|
return [int(line) for line in inputs.split()]
|
|
|
|
|
|
def solve(path: str) -> Tuple[int, int]:
|
|
"""Solve the puzzle"""
|
|
puzzle_input = parse(pathlib.Path(path).read_text().strip())
|
|
part1_result = part1(puzzle_input)
|
|
part2_result = part2(puzzle_input)
|
|
|
|
return part1_result, part2_result
|
|
|
|
|
|
def main() -> None:
|
|
for path in sys.argv[1:]:
|
|
print(f"Input File: {path}")
|
|
|
|
part1_result, part2_result = solve(path)
|
|
|
|
print(f"Part 1 Result: {part1_result}")
|
|
print(f"Part 2 Result: {part2_result}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|