Загрузка данных


class Node:
    def __init__(self, val):
        self.val = val
        self.next = None
        self.prev = None




class Double_Linked_List:
    def __init__(self, *lst):
        self.head = self.tail = None
        self.size = 0


        for node in lst:
            self.append(node)
      
      
    def __len__(self):
        return self.size


    def __str__(self):
        if not self.head:
            return "empty"
        cur = self.head
        res = ""
        while cur:
            if not cur.next:
                res +=f"{cur.val}"
                break
            res +=f"{cur.val}<>"
            cur = cur.next
        return res
        
           
        


    def __iter__(self):
        cur = self.head
        while cur:
            yield cur.val
            cur = cur.next


    def __reversed__(self):
        cur = self.tail
        while cur:
            yield cur.val
            cur = cur.prev


    def is_empty(self):
        return self.size == 0


    def _node_at(self, idx):
        if idx < 0:
            idx += self.size


        if idx < 0 or idx >= self.size:
            raise IndexError("index out of range")


   
        if idx < self.size // 2:
            cur = self.head
            for _ in range(idx):
                cur = cur.next
        else:
            cur = self.tail
            for _ in range(self.size - 1, idx, -1):
                cur = cur.prev


        return cur


    
    def __get_item__(self, idx):
        return self._node_at(idx)


    def __getitem__(self, idx):
        return self._node_at(idx).val


    def __setitem__(self, idx, value):
        self._node_at(idx).val = value


    def append(self, val):
        new_node = Node(val)
        self.size +=1
        if not self.head:
            self.head= self.tail = new_node
            new_node.prev =self.tail
            self.tail =new_node


    def insert(self, idx, val):
      
      
      
        if idx < 0:
            idx = max(0, self.size + idx)
        else:
            idx = min(idx, self.size)


        if idx == self.size:
            self.append(val)
            return


        new_node = Node(val)


        if idx == 0:
            new_node.next = self.head
            self.head.prev = new_node
            self.head = new_node
        else:
            right = self._node_at(idx)
            left = right.prev


            new_node.prev = left
            new_node.next = right
            left.next = new_node
            right.prev = new_node


        self.size += 1


    def remove(self, val):
        cur = self.head


        while cur and cur.val != val:
            cur = cur.next


        if cur is None:
            raise ValueError(f"{val} not in list")


        if cur.prev:
            cur.prev.next = cur.next
        else:
            self.head = cur.next


        if cur.next:
            cur.next.prev = cur.prev
        else:
            self.tail = cur.prev


        self.size -= 1


    def pop(self, idx=-1):
        node = self._node_at(idx)
        value = node.val


        if node.prev:
            node.prev.next = node.next
        else:
            self.head = node.next


        if node.next:
            node.next.prev = node.prev
        else:
            self.tail = node.prev


        self.size -= 1
        return value


    def swap(self, idx1, idx2):
        node1 = self._node_at(idx1)
        node2 = self._node_at(idx2)
        node1.val, node2.val = node2.val, node1.val


    def reverse(self):
        cur = self.head


        while cur:
         
            cur.prev, cur.next = cur.next, cur.prev
            cur = cur.prev


        self.head, self.tail = self.tail, self.head