from __future__ import annotations from dataclasses import dataclass import logging from typing import List, Self class color: PURPLE = "\033[95m" CYAN = "\033[96m" DARKCYAN = "\033[36m" BLUE = "\033[94m" GREEN = "\033[92m" YELLOW = "\033[93m" RED = "\033[91m" BOLD = "\033[1m" UNDERLINE = "\033[4m" END = "\033[0m" @dataclass(init=False, eq=False) class OASISLine: sequence: List[int] reduce_map: List[List[int]] def __init__(self, input_line: str): self.sequence = list(map(lambda i: int(i), input_line.split(" "))) self.reduce_map = [ self.sequence, ] def reduce(self) -> Self: logging.debug(color.RED + f"reducing {self.sequence}" + color.END) logging.debug(color.BLUE + "=".join(["" for i in range(40)]) + color.END) line = self.sequence logging.debug(str(line)) while not all(map(lambda i: i == 0, line)): new_line = [] for idx, number in enumerate(line): if idx > 0: new_line.append(number - line[idx - 1]) line = new_line self.reduce_map.append(line) logging.debug(str(line)) logging.debug(color.BLUE + "=".join(["" for i in range(40)]) + color.END) return self def extrapolate(self): logging.debug(color.RED + f"extrapolating {self.sequence}" + color.END) logging.debug(color.BLUE + "=".join(["" for i in range(40)]) + color.END) next_increment = 0 for line in reversed(self.reduce_map): if all(map(lambda i: i == line[0], line)): next_increment = line[0] else: next_increment = line[len(line) - 1] + next_increment logging.debug(str(line) + " " + color.BOLD + color.GREEN + f" {next_increment}" + color.END + "\n") logging.debug(color.BLUE + "=".join(["" for i in range(40)]) + color.END) return next_increment def extrapolate_back(self): logging.debug(color.RED + f"extrapolating back {self.sequence}" + color.END) logging.debug(color.BLUE + "=".join(["" for i in range(40)]) + color.END) next_increment = 0 for line in reversed(self.reduce_map): if all(map(lambda i: i == line[0], line)): next_increment = line[0] else: next_increment = line[0] - next_increment logging.debug(color.BOLD + color.GREEN + f"{next_increment} " + color.END + str(line)) logging.debug(color.BLUE + "=".join(["" for i in range(40)]) + color.END) return next_increment @classmethod def parse(cls, input_file: str) -> List[OASISLine]: the_list = [] with open(input_file) as input: while line := input.readline(): line = line.rstrip("\n").rstrip() logging.debug(color.RED + f'parsing "{line}"' + color.END) the_list.append(OASISLine(line)) logging.debug(color.GREEN + f"parsed {the_list[len(the_list) - 1].sequence}" + color.END) return the_list