thiagowfx's avatar

Β¬ just serendipity πŸ€ (not just serendipity)

queue

β€’ 413 words β€’ 2 min β€’ updated

Problem statement: Implement a glorified Queue class.

Employ:

  • type annotations
  • custom exceptions
  • comparison operators
  • classic queue contract
  • iterators
  • hashes
python
#!/usr/bin/env python3

from collections import deque
from collections.abc import Iterator

from copy import deepcopy

from typing import TypeVar, Generic, Iterable

T = TypeVar('T')

class Queueis_empty(Exception):
    ...

class Queue(Generic[T]):
    def __init__(self, iterable: Iterable[T] = []) -> None:
        self.d: deque[T] = deque(iterable)

    def __len__(self) -> int:
        return len(self.d)

    def size(self) -> int:
        return self.__len__()

    def is_empty(self) -> bool:
        return self.__len__() == 0

    def queue(self, val: T) -> None:
        self.d.append(val)

    def dequeue(self) -> T:
        self._check_is_empty()
        return self.d.popleft()

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Queue):
            return False
        return self.d == other.d

    def __ne__(self, other: object) -> bool:
        if not isinstance(other, Queue):
            return False
        return self.d != other.d


    def _check_is_empty(self) -> None:
        if self.is_empty():
            raise Queueis_empty('cannot dequeue from is_empty queue')

    def __contains__(self, val) -> bool:
        return val in self.d

    def __str__(self) -> str:
        return f'Queue{list(self.d)}'

    def __repr__(self) -> str:
        return self.__str__()

    def peek(self) -> T:
        self._check_is_empty()
        return self.d[0]

    def clear(self) -> None:
        ## self.d = deque()
        self.d.clear()

    def to_list(self) -> list[T]:
        return list(self.d)

    def __iter__(self) -> Iterator[T]:
        return iter(self.d)

    def __hash__(self) -> int:
        return hash(tuple(self.d))

    def __le__(self, other: 'Queue[T]') -> bool:
        if not isinstance(other, Queue):
            return NotImplemented
        return len(self) <= len(other)

    def __lt__(self, other: 'Queue[T]') -> bool:
        if not isinstance(other, Queue):
            return NotImplemented
        return len(self) < len(other)

    def copy(self) -> 'Queue[T]':
        return Queue(self.d.copy())

    def deepcopy(self) -> 'Queue[T]':
        return Queue(deepcopy(self.d))

    def __reversed__(self) -> Iterator[T]:
        return reversed(self.d)


if __name__ == "__main__":
    q = Queue()
    assert len(q) == 0
    assert q.is_empty()

    q.queue(1)
    assert not q.is_empty()
    assert len(q) == 1
    q.queue(2)
    assert len(q) == 2

    assert q.dequeue() == 1
    assert len(q) == 1

    assert q.dequeue() == 2

    try:
        q.dequeue()
        assert False
    except Exception as e:
        assert str(e) == 'cannot dequeue from is_empty queue'

    q.queue(1)
    q.queue(2)

    w = Queue([1, 2])

    r = Queue()

    assert q == w
    assert q != r

    assert 1 in q
    assert 1 not in r

    assert str(q) == 'Queue[1, 2]'
    assert str(q) == str(w)

    assert q.size() == 2 == len(q)

    assert q.peek() == 1

    q.clear()
    assert len(q) == 0

    assert q.to_list() == []
    assert w.to_list() == [1, 2]

    assert list(q) == []

    z  = w.copy()
    z.dequeue()
    assert len(z) == 1
    assert len(w) == 2

    q = Queue([set([1])])
    w = q.copy()

    q.peek().add(2)
    assert len(q.peek()) == 2
    assert len(w.peek()) == 2

    w = q.deepcopy()
    q.peek().add(3)
    assert len(q.peek()) == 3
    assert len(w.peek()) == 2

    assert len(set([Queue([1, 2]), Queue([1, 2])])) == 1
    assert len(set([Queue([1, 2]), Queue([1, 3])])) == 2