130 lines
3.0 KiB
Python
130 lines
3.0 KiB
Python
from tools.aoc import AOCDay
|
|
from typing import Any
|
|
|
|
|
|
class Node:
|
|
def __init__(self, node_id: int, value: int):
|
|
self.node_id = node_id
|
|
self.value = value
|
|
self.left = None
|
|
self.right = None
|
|
|
|
def __str__(self):
|
|
return f"Node(id={self.node_id}; value={self.value}; left={self.left.node_id}; right={self.right.node_id})"
|
|
|
|
def __len__(self):
|
|
ptr = self
|
|
length = 0
|
|
while ptr.right != self:
|
|
length += 1
|
|
ptr = ptr.right
|
|
|
|
return length + 1
|
|
|
|
|
|
def mix(head: Node) -> Node:
|
|
ptr = head
|
|
list_len = len(head)
|
|
for i in range(list_len):
|
|
while ptr.node_id != i:
|
|
ptr = ptr.right
|
|
cur_val = ptr.value
|
|
cur_ptr = ptr
|
|
|
|
if cur_val == 0:
|
|
continue
|
|
|
|
if cur_ptr == head:
|
|
head = cur_ptr.right
|
|
|
|
cur_ptr.left.right = cur_ptr.right
|
|
cur_ptr.right.left = cur_ptr.left
|
|
|
|
target_ptr = cur_ptr
|
|
if cur_val > 0:
|
|
cur_val = cur_val % list_len + (cur_val // list_len) % (list_len - 1)
|
|
else:
|
|
cur_val = -(abs(cur_val) % list_len + (abs(cur_val) // list_len) % (list_len - 1))
|
|
|
|
for _ in range(abs(cur_val)):
|
|
if cur_val < 0:
|
|
target_ptr = target_ptr.left
|
|
else:
|
|
target_ptr = target_ptr.right
|
|
|
|
if cur_val < 0:
|
|
cur_ptr.left = target_ptr.left
|
|
cur_ptr.right = target_ptr
|
|
target_ptr.left.right = cur_ptr
|
|
target_ptr.left = cur_ptr
|
|
else:
|
|
cur_ptr.left = target_ptr
|
|
cur_ptr.right = target_ptr.right
|
|
target_ptr.right.left = cur_ptr
|
|
target_ptr.right = cur_ptr
|
|
|
|
return head
|
|
|
|
|
|
def coord_sum(ptr: Node) -> int:
|
|
while ptr.value != 0:
|
|
ptr = ptr.right
|
|
|
|
val_sum = 0
|
|
for _ in range(3):
|
|
for _ in range(1000):
|
|
ptr = ptr.right
|
|
val_sum += ptr.value
|
|
|
|
return val_sum
|
|
|
|
|
|
class Day(AOCDay):
|
|
inputs = [
|
|
[
|
|
(3, "input20_test"),
|
|
(4, "input20_test2"),
|
|
(10763, "input20"),
|
|
],
|
|
[
|
|
(1623178306, "input20_test"),
|
|
(4979911042808, "input20"),
|
|
]
|
|
]
|
|
|
|
def get_inp_llist(self, mul: int = 1) -> Node:
|
|
head = None
|
|
tail = None
|
|
for i, x in enumerate(self.getInput(int)):
|
|
n = Node(i, x * mul)
|
|
if head is None:
|
|
head = n
|
|
tail = n
|
|
else:
|
|
tail.right = n
|
|
n.left = tail
|
|
tail = n
|
|
|
|
tail.right = head
|
|
head.left = tail
|
|
|
|
return head
|
|
|
|
def part1(self) -> Any:
|
|
ptr = self.get_inp_llist()
|
|
ptr = mix(ptr)
|
|
return coord_sum(ptr)
|
|
|
|
|
|
def part2(self) -> Any:
|
|
key = 811589153
|
|
ptr = self.get_inp_llist(key)
|
|
for _ in range(10):
|
|
ptr = mix(ptr)
|
|
return coord_sum(ptr)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
day = Day(2022, 20)
|
|
day.run(verbose=True)
|