Day 20, slow.

This commit is contained in:
Mikael CAPELLE 2022-12-20 13:39:36 +01:00
parent df808bc98a
commit 1bf2de62c7

View File

@ -1,24 +1,26 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
import math
import sys import sys
class Number: class Number:
processed: bool index: int
value: int value: int
def __init__(self, value: int): def __init__(self, index: int, value: int):
self.index = index
self.value = value self.value = value
self.processed = False
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, Number): if isinstance(other, Number):
return self.value == other.value return self.index == other.index
elif isinstance(other, int): elif isinstance(other, int):
return self.value == other return self.value == other
return False return False
def __hash__(self):
return hash(self.index)
def __str__(self): def __str__(self):
return str(self.value) return str(self.value)
@ -26,79 +28,43 @@ class Number:
return str(self) return str(self)
expected = iter( def decrypt(numbers: list[Number], key: int, rounds: int) -> int:
[
[1, 2, -3, 3, -2, 0, 4],
[2, 1, -3, 3, -2, 0, 4],
[1, -3, 2, 3, -2, 0, 4],
[1, 2, 3, -2, -3, 0, 4],
[1, 2, -2, -3, 0, 3, 4],
[1, 2, -3, 0, 3, 4, -2],
[1, 2, -3, 0, 3, 4, -2],
[1, 2, -3, 4, 0, 3, -2],
]
)
numbers = numbers.copy()
original = numbers.copy()
numbers2index = {number: number.index for number in numbers}
numbers = [Number(int(x)) for x in sys.stdin.readlines()] def swap(lhs: Number, rhs: Number):
# numbers = [Number(0), Number(0), Number(-6)] i1, i2 = numbers2index[lhs], numbers2index[rhs]
numbers[i1], numbers[i2] = numbers[i2], numbers[i1]
numbers2index[lhs], numbers2index[rhs] = i2, i1
# print(next(expected)) def move(index: int, value: int):
# print(numbers) assert value >= 0
# print("---") while value > 0:
if index == len(numbers) - 1:
index = 0 swap(numbers[0], numbers[-1])
while index < len(numbers): index, value = 0, value - 1
if numbers[index].processed:
index += 1
continue
number = numbers[index]
number.processed = True
target = (
index
+ (number.value % len(numbers))
- int(number.value < 0) * math.ceil(abs(number.value) / len(numbers))
) % len(numbers)
# print(
# f"moving {number} from {index} to {target} (between {numbers[target]} and {numbers[(target + 1) % len(numbers)]})"
# )
if target == index:
index += 1
elif target == index + 1:
numbers[index], numbers[target] = numbers[target], numbers[index]
elif target == index - 1:
numbers[index], numbers[target] = numbers[target], numbers[index]
elif target > index:
# print(
# numbers[:index],
# numbers[index + 1 : target + 1],
# [numbers[index]],
# numbers[target + 1 :],
# )
numbers = (
numbers[:index]
+ numbers[index + 1 : target + 1]
+ [numbers[index]]
+ numbers[target + 1 :]
)
else: else:
numbers = ( swap(numbers[index + 1], numbers[index])
numbers[: target + 1] index, value = index + 1, value - 1
+ [numbers[index]]
+ numbers[target + 1 : index] for _ in range(rounds):
+ numbers[index + 1 :] for number in original:
index = numbers2index[number]
move(index, (number.value * key) % (len(numbers) - 1))
index_of_0 = numbers.index(0)
return sum(
numbers[(index_of_0 + offset) % len(numbers)].value * key
for offset in (1000, 2000, 3000)
) )
index -= 1
# print(next(expected))
# print(numbers)
# print("---")
index_of_0 = numbers.index(Number(0)) numbers = [Number(i, int(x)) for i, x in enumerate(sys.stdin.readlines())]
answer_1 = sum( answer_1 = decrypt(numbers, 1, 1)
numbers[(index_of_0 + offset) % len(numbers)].value for offset in (1000, 2000, 3000)
)
print(f"answer 1 is {answer_1}") print(f"answer 1 is {answer_1}")
answer_2 = decrypt(numbers, 811589153, 10)
print(f"answer 2 is {answer_2}")