Day 20, slow.
This commit is contained in:
parent
835458e0f3
commit
ed00c72e59
120
2022/day20.py
120
2022/day20.py
@ -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],
|
numbers = numbers.copy()
|
||||||
[2, 1, -3, 3, -2, 0, 4],
|
original = numbers.copy()
|
||||||
[1, -3, 2, 3, -2, 0, 4],
|
numbers2index = {number: number.index for number in numbers}
|
||||||
[1, 2, 3, -2, -3, 0, 4],
|
|
||||||
[1, 2, -2, -3, 0, 3, 4],
|
def swap(lhs: Number, rhs: Number):
|
||||||
[1, 2, -3, 0, 3, 4, -2],
|
i1, i2 = numbers2index[lhs], numbers2index[rhs]
|
||||||
[1, 2, -3, 0, 3, 4, -2],
|
numbers[i1], numbers[i2] = numbers[i2], numbers[i1]
|
||||||
[1, 2, -3, 4, 0, 3, -2],
|
numbers2index[lhs], numbers2index[rhs] = i2, i1
|
||||||
]
|
|
||||||
)
|
def move(index: int, value: int):
|
||||||
|
assert value >= 0
|
||||||
|
while value > 0:
|
||||||
|
if index == len(numbers) - 1:
|
||||||
|
swap(numbers[0], numbers[-1])
|
||||||
|
index, value = 0, value - 1
|
||||||
|
else:
|
||||||
|
swap(numbers[index + 1], numbers[index])
|
||||||
|
index, value = index + 1, value - 1
|
||||||
|
|
||||||
|
for _ in range(rounds):
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
numbers = [Number(int(x)) for x in sys.stdin.readlines()]
|
numbers = [Number(i, int(x)) for i, x in enumerate(sys.stdin.readlines())]
|
||||||
# numbers = [Number(0), Number(0), Number(-6)]
|
|
||||||
|
|
||||||
# print(next(expected))
|
answer_1 = decrypt(numbers, 1, 1)
|
||||||
# print(numbers)
|
|
||||||
# print("---")
|
|
||||||
|
|
||||||
index = 0
|
|
||||||
while index < len(numbers):
|
|
||||||
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:
|
|
||||||
numbers = (
|
|
||||||
numbers[: target + 1]
|
|
||||||
+ [numbers[index]]
|
|
||||||
+ numbers[target + 1 : index]
|
|
||||||
+ numbers[index + 1 :]
|
|
||||||
)
|
|
||||||
index -= 1
|
|
||||||
|
|
||||||
# print(next(expected))
|
|
||||||
# print(numbers)
|
|
||||||
# print("---")
|
|
||||||
|
|
||||||
index_of_0 = numbers.index(Number(0))
|
|
||||||
|
|
||||||
answer_1 = sum(
|
|
||||||
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}")
|
||||||
|
Loading…
Reference in New Issue
Block a user