from typing import Any, Iterator from ..base import BaseSolver def mix(secret: int, value: int) -> int: return secret ^ value def prune(secret: int) -> int: return secret % 16777216 def next_number(secret: int) -> int: # Calculate the result of multiplying the secret number by 64. Then, mix this # result into the secret number. Finally, prune the secret number. secret = prune(mix(secret, secret * 64)) # Calculate the result of dividing the secret number by 32. Round the result down # to the nearest integer. Then, mix this result into the secret number. Finally, # prune the secret number. secret = prune(mix(secret, secret // 32)) # Calculate the result of multiplying the secret number by 2048. Then, mix this # result into the secret number. Finally, prune the secret number. secret = prune(mix(secret, secret * 2048)) return secret class Solver(BaseSolver): def solve(self, input: str) -> Iterator[Any]: starts = [int(r) for r in input.splitlines()] ends: list[int] = [] prices: list[int] = [0 for _ in range(2**16)] for secret in self.progress.wrap(starts): checked: list[bool] = [False] * len(prices) hashed: int = 0 for i in range(2000): last = secret % 10 secret = next_number(secret) next = secret % 10 hashed = ((hashed << 4) & 0xFFFF) | ((last - next) & 0xF) if i >= 3 and not checked[hashed]: checked[hashed] = True prices[hashed] += next ends.append(secret) for start, end in zip(starts, ends, strict=True): self.logger.info(f"{start}: {end}") yield sum(ends) yield max(prices)