Co-authored-by: Mikael CAPELLE <mikael.capelle@thalesaleniaspace.com> Co-authored-by: Mikaël Capelle <capelle.mikael@gmail.com> Reviewed-on: #3
76 lines
2.0 KiB
Python
76 lines
2.0 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any, Iterator
|
|
|
|
from ..base import BaseSolver
|
|
|
|
|
|
class Number:
|
|
current: int
|
|
value: int
|
|
|
|
def __init__(self, value: int):
|
|
self.current = 0
|
|
self.value = value
|
|
|
|
def __str__(self):
|
|
return str(self.value)
|
|
|
|
def __repr__(self):
|
|
return str(self)
|
|
|
|
|
|
def decrypt(numbers: list[Number], key: int, rounds: int) -> int:
|
|
numbers = numbers.copy()
|
|
original = numbers.copy()
|
|
|
|
for index, number in enumerate(numbers):
|
|
number.current = index
|
|
|
|
for _ in range(rounds):
|
|
for number in original:
|
|
index = number.current
|
|
offset = (number.value * key) % (len(numbers) - 1)
|
|
target = index + offset
|
|
|
|
# need to wrap
|
|
if target >= len(numbers):
|
|
target = offset - (len(numbers) - index) + 1
|
|
|
|
for number_2 in numbers[target:index]:
|
|
number_2.current += 1
|
|
|
|
numbers = (
|
|
numbers[:target]
|
|
+ [number]
|
|
+ numbers[target:index]
|
|
+ numbers[index + 1 :]
|
|
)
|
|
else:
|
|
for number_2 in numbers[index : target + 1]:
|
|
number_2.current -= 1
|
|
|
|
numbers = (
|
|
numbers[:index]
|
|
+ numbers[index + 1 : target + 1]
|
|
+ [number]
|
|
+ numbers[target + 1 :]
|
|
)
|
|
number.current = target
|
|
|
|
index_of_0 = next(
|
|
filter(lambda index: numbers[index].value == 0, range(len(numbers)))
|
|
)
|
|
return sum(
|
|
numbers[(index_of_0 + offset) % len(numbers)].value * key
|
|
for offset in (1000, 2000, 3000)
|
|
)
|
|
|
|
|
|
class Solver(BaseSolver):
|
|
def solve(self, input: str) -> Iterator[Any]:
|
|
numbers = [Number(int(x)) for x in input.splitlines()]
|
|
|
|
yield decrypt(numbers, 1, 1)
|
|
yield decrypt(numbers, 811589153, 10)
|