Queue implementation using two stacks from collections.abc import Iterable from typing import Generic, TypeVar T  TypeVarT class QueueByTwoStacksGenericT: def initself, iterable: IterableT  None  None  None: self.stack1: listT  listiterable or  self.stack2: listT   def lenself  int: return lenself.stack1  lenself.stack2 def reprself  str: return fQueuetupleself.stack2::1  self.stack1 def putself, item: T  None: self.stack1.appenditem def getself  T: To reduce number of attribute lookups in while loop. stack1pop  self.stack1.pop stack2append  self.stack2.append if not self.stack2: while self.stack1: stack2appendstack1pop if not self.stack2: raise IndexErrorQueue is empty return self.stack2.pop if name  main: from doctest import testmod testmod
from collections.abc import Iterable
from typing import Generic, TypeVar

_T = TypeVar("_T")


class QueueByTwoStacks(Generic[_T]):
    def __init__(self, iterable: Iterable[_T] | None = None) -> None:
        """
        >>> QueueByTwoStacks()
        Queue(())
        >>> QueueByTwoStacks([10, 20, 30])
        Queue((10, 20, 30))
        >>> QueueByTwoStacks((i**2 for i in range(1, 4)))
        Queue((1, 4, 9))
        """
        self._stack1: list[_T] = list(iterable or [])
        self._stack2: list[_T] = []

    def __len__(self) -> int:
        """
        >>> len(QueueByTwoStacks())
        0
        >>> from string import ascii_lowercase
        >>> len(QueueByTwoStacks(ascii_lowercase))
        26
        >>> queue = QueueByTwoStacks()
        >>> for i in range(1, 11):
        ...     queue.put(i)
        ...
        >>> len(queue)
        10
        >>> for i in range(2):
        ...   queue.get()
        1
        2
        >>> len(queue)
        8
        """

        return len(self._stack1) + len(self._stack2)

    def __repr__(self) -> str:
        """
        >>> queue = QueueByTwoStacks()
        >>> queue
        Queue(())
        >>> str(queue)
        'Queue(())'
        >>> queue.put(10)
        >>> queue
        Queue((10,))
        >>> queue.put(20)
        >>> queue.put(30)
        >>> queue
        Queue((10, 20, 30))
        """
        return f"Queue({tuple(self._stack2[::-1] + self._stack1)})"

    def put(self, item: _T) -> None:
        """
        Put `item` into the Queue

        >>> queue = QueueByTwoStacks()
        >>> queue.put(10)
        >>> queue.put(20)
        >>> len(queue)
        2
        >>> queue
        Queue((10, 20))
        """

        self._stack1.append(item)

    def get(self) -> _T:
        """
        Get `item` from the Queue

        >>> queue = QueueByTwoStacks((10, 20, 30))
        >>> queue.get()
        10
        >>> queue.put(40)
        >>> queue.get()
        20
        >>> queue.get()
        30
        >>> len(queue)
        1
        >>> queue.get()
        40
        >>> queue.get()
        Traceback (most recent call last):
            ...
        IndexError: Queue is empty
        """

        # To reduce number of attribute look-ups in `while` loop.
        stack1_pop = self._stack1.pop
        stack2_append = self._stack2.append

        if not self._stack2:
            while self._stack1:
                stack2_append(stack1_pop())

        if not self._stack2:
            raise IndexError("Queue is empty")
        return self._stack2.pop()


if __name__ == "__main__":
    from doctest import testmod

    testmod()
