class DLinkedList: def __init__(self) -> None: self._len = 0 self._head = _Node() self._head.next = self._head self._head.prev = self._head self._curr: Tuple[_Node, int] = (self._head, 1) def at_head(self) -> bool: if self._curr[0] is self._head: return True else: return False def get_curr(self) -> Tuple[Any, int]: return (self._curr[0].data, self._curr[1]) def set_curr(self, data: Any) -> None: if self.at_head(): raise IndexError("Empty or curr is at head (try next or prev?)") else: self._curr[0].data = data def next(self, n: int = 1) -> Tuple[Any, int]: """Move the current position one forward""" temp_node, temp_index = self._curr[0], self._curr[1] for i in range(n): temp_node = temp_node.next temp_index = -1 if temp_node is self._head else temp_index + 1 self._curr = (temp_node, self._len if temp_node is self._head else temp_index) return self.get_curr() def prev(self, n: int = 1) -> Tuple[Any, int]: """Move the current position one forward""" temp_node, temp_index = self._curr[0], self._curr[1] for _ in range(n): temp_node = temp_node.prev temp_index = self._len if temp_node is self._head else temp_index - 1 self._curr = (temp_node, temp_index) return self.get_curr() def __len__(self) -> int: return self._len def __getitem__(self, index: int) -> Any: tmp = self._head.next for _ in range(index): if tmp is self._head: break else: tmp = tmp.next return tmp.data class _Node: def __init__(self, data: Any = None, prev: Union[_Node, None] = None, next: Union[_Node, None] = None) -> None: self.data = data self.prev = prev self.next = next