Source code for day09.day9
"""day9 solution."""
from dataclasses import dataclass
from typing import Callable
INPUT = "day09/input.txt"
INPUT_SMALL = "day09/input-small.txt"
[docs]
@dataclass
class ValueArray:
"""Class representing an array and its subarrays."""
sub_arrays: list[list[int]]
def __post_init__(self) -> None:
"""Creates sub arrays."""
current: list[int] = self.sub_arrays[0]
while set(current) != {0}:
current = interpolate(current)
self.sub_arrays.append(current)
[docs]
def generic_extrapolate(
self,
add_to_array: Callable[[list[int], int], None],
calc_value: Callable[[list[int], list[int]], int],
) -> None:
"""Generic extrapolation."""
for i in range(-1, -len(self.sub_arrays) - 1, -1):
array: list[int] = self.sub_arrays[i]
if i == -1:
add_to_array(array, 0)
else:
array_below: list[int] = self.sub_arrays[i + 1]
new_value = calc_value(array, array_below)
add_to_array(array, new_value)
[docs]
def extrapolate_right(self) -> None:
"""Extrapolates to the right."""
def add_to_array(array: list[int], value: int) -> None:
array.append(value)
def calculate_value(array: list[int], array_below: list[int]) -> int:
return array[-1] + array_below[-1]
self.generic_extrapolate(add_to_array, calculate_value)
[docs]
def extrapolate_left(self) -> None:
"""Extrapolates to the left."""
def add_to_array(array: list[int], value: int) -> None:
array.insert(0, value)
def calculate_value(array: list[int], array_below: list[int]) -> int:
return array[0] - array_below[0]
self.generic_extrapolate(add_to_array, calculate_value)
[docs]
def get_input(path: str) -> list[ValueArray]:
"""Turns inputs into nice ValueArrays."""
result = []
with open(path, "r", encoding="utf8") as file:
for line in file:
values = ValueArray([[int(item) for item in line.split()]])
result.append(values)
return result
[docs]
def interpolate(values: list[int]) -> list[int]:
"""Interpolate a list using element-wise diffs.
Converts ``3 3 3 3``
to ``0 0 0``
Converts ``1 2 3 4``
to ``1 1 1``
Args:
values (list[int]): list of values
Returns:
list[int]: interpolated list
"""
result = [values[i + 1] - values[i] for i in range(len(values) - 1)]
return result
[docs]
def part1(inputs: list[ValueArray]) -> int:
"""Interpolates then extrapolates array to the right."""
for input in inputs:
input.extrapolate_right()
return sum(input.sub_arrays[0][-1] for input in inputs)
[docs]
def part2(inputs: list[ValueArray]) -> int:
"""Interpolates then extrapolates array to the left."""
for input in inputs:
input.extrapolate_left()
return sum(input.sub_arrays[0][0] for input in inputs)
[docs]
def main() -> None:
"""Main function."""
inputs = get_input(INPUT)
# q1
print(part1(inputs))
# q2
print(part2(inputs))
if __name__ == "__main__":
main()