From 49ce66138f79be0914052d7bb834f1f3f1b0b3b0 Mon Sep 17 00:00:00 2001 From: Amirsoroush Date: Fri, 7 Apr 2023 19:55:26 +0300 Subject: [PATCH 1/7] Queue implementation using two Stacks --- data_structures/queue/queue_on_two_stacks.py | 123 +++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 data_structures/queue/queue_on_two_stacks.py diff --git a/data_structures/queue/queue_on_two_stacks.py b/data_structures/queue/queue_on_two_stacks.py new file mode 100644 index 000000000000..7db39eaf2712 --- /dev/null +++ b/data_structures/queue/queue_on_two_stacks.py @@ -0,0 +1,123 @@ +"""Queue implementation using two stacks""" + +from typing import Any + + +class Queue: + def __init__(self) -> None: + self._stack1: list[Any] = [] + self._stack2: list[Any] = [] + + def put(self, item: Any) -> None: + """ + Put `item` into the Queue + + >>> queue = Queue() + >>> queue.put(10) + >>> queue.put(20) + >>> len(queue) == 2 + True + >>> str(queue) + '<[10, 20]>' + """ + + self._stack1.append(item) + + def get(self) -> Any: + """ + Get `item` from the Queue + + >>> queue = Queue() + >>> for i in (10, 20, 30): + ... queue.put(i) + >>> len(queue) + 3 + >>> queue.get() + 10 + >>> queue.get() + 20 + >>> len(queue) == 1 + True + >>> queue.get() + 30 + >>> queue.get() + Traceback (most recent call last): + ... + IndexError: Queue is empty + """ + + # To reduce number of attribtue 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() + + def size(self) -> int: + """ + Returns the length of the Queue + + >>> queue = Queue() + >>> queue.size() + 0 + >>> queue.put(10) + >>> queue.put(20) + >>> queue.size() + 2 + >>> queue.get() + 10 + >>> queue.size() == 1 + True + """ + + return len(self) + + def __str__(self) -> str: + """ + >>> queue = Queue() + >>> str(queue) + '<[]>' + >>> queue.put(10) + >>> str(queue) + '<[10]>' + >>> queue.put(20) + >>> str(queue) + '<[10, 20]>' + >>> queue.get() + 10 + >>> queue.put(30) + >>> str(queue) == '<[20, 30]>' + True + """ + + return f"<{self._stack2[::-1] + self._stack1}>" + + def __len__(self) -> int: + """ + >>> queue = Queue() + >>> for i in range(1, 11): + ... queue.put(i) + ... + >>> len(queue) == 10 + True + >>> for i in range(2): + ... queue.get() + ... + 1 + 2 + >>> len(queue) == 8 + True + """ + + return len(self._stack1) + len(self._stack2) + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From 37bd353a2093e7a5fc99758e1e6277d30dc974b2 Mon Sep 17 00:00:00 2001 From: Amirsoroush Date: Fri, 7 Apr 2023 20:18:03 +0300 Subject: [PATCH 2/7] fix typo in queue/queue_on_two_stacks.py --- data_structures/queue/queue_on_two_stacks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/queue/queue_on_two_stacks.py b/data_structures/queue/queue_on_two_stacks.py index 7db39eaf2712..0cdb46c7ed62 100644 --- a/data_structures/queue/queue_on_two_stacks.py +++ b/data_structures/queue/queue_on_two_stacks.py @@ -46,7 +46,7 @@ def get(self) -> Any: IndexError: Queue is empty """ - # To reduce number of attribtue look-ups in `while` loop. + # To reduce number of attribute look-ups in `while` loop. stack1_pop = self._stack1.pop stack2_append = self._stack2.append From 1da0297afc88d7db8a97caa3f3925af96c6d7b5b Mon Sep 17 00:00:00 2001 From: Amirsoroush Date: Sat, 8 Apr 2023 09:50:19 +0300 Subject: [PATCH 3/7] add 'iterable' to queue_on_two_stacks initializer --- data_structures/queue/queue_on_two_stacks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/queue/queue_on_two_stacks.py b/data_structures/queue/queue_on_two_stacks.py index 0cdb46c7ed62..8bdac68aed15 100644 --- a/data_structures/queue/queue_on_two_stacks.py +++ b/data_structures/queue/queue_on_two_stacks.py @@ -4,8 +4,8 @@ class Queue: - def __init__(self) -> None: - self._stack1: list[Any] = [] + def __init__(self, iterable=None) -> None: + self._stack1: list[Any] = [] if iterable is None else list(iterable) self._stack2: list[Any] = [] def put(self, item: Any) -> None: From 100ec02e894c4c6f00b634014a903fa6c6d37f1a Mon Sep 17 00:00:00 2001 From: Amirsoroush Date: Sat, 8 Apr 2023 10:05:52 +0300 Subject: [PATCH 4/7] make queue_on_two_stacks.py generic class --- data_structures/queue/queue_on_two_stacks.py | 29 +++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/data_structures/queue/queue_on_two_stacks.py b/data_structures/queue/queue_on_two_stacks.py index 8bdac68aed15..fe2caa60a42a 100644 --- a/data_structures/queue/queue_on_two_stacks.py +++ b/data_structures/queue/queue_on_two_stacks.py @@ -1,14 +1,29 @@ """Queue implementation using two stacks""" -from typing import Any +from collections.abc import Iterable +from typing import Generic, Optional, TypeVar +_T = TypeVar("_T") -class Queue: - def __init__(self, iterable=None) -> None: - self._stack1: list[Any] = [] if iterable is None else list(iterable) - self._stack2: list[Any] = [] - def put(self, item: Any) -> None: +class Queue(Generic[_T]): + def __init__(self, iterable: Optional[Iterable[_T]] = None) -> None: + """ + >>> queue1 = Queue() + >>> str(queue1) + '<[]>' + >>> queue2 = Queue([10, 20, 30]) + >>> str(queue2) + '<[10, 20, 30]>' + >>> queue3 = Queue((i**2 for i in range(1, 4))) + >>> str(queue3) + '<[1, 4, 9]>' + """ + + self._stack1: list[_T] = [] if iterable is None else list(iterable) + self._stack2: list[_T] = [] + + def put(self, item: _T) -> None: """ Put `item` into the Queue @@ -23,7 +38,7 @@ def put(self, item: Any) -> None: self._stack1.append(item) - def get(self) -> Any: + def get(self) -> _T: """ Get `item` from the Queue From d9accd5aa985c84ba71872aa11e396bf6d774eb0 Mon Sep 17 00:00:00 2001 From: Amirsoroush Date: Sat, 8 Apr 2023 10:21:18 +0300 Subject: [PATCH 5/7] fix ruff-UP007 in queue_on_two_stacks.py --- data_structures/queue/queue_on_two_stacks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/queue/queue_on_two_stacks.py b/data_structures/queue/queue_on_two_stacks.py index fe2caa60a42a..6395d1695b79 100644 --- a/data_structures/queue/queue_on_two_stacks.py +++ b/data_structures/queue/queue_on_two_stacks.py @@ -1,13 +1,13 @@ """Queue implementation using two stacks""" from collections.abc import Iterable -from typing import Generic, Optional, TypeVar +from typing import Generic, TypeVar _T = TypeVar("_T") class Queue(Generic[_T]): - def __init__(self, iterable: Optional[Iterable[_T]] = None) -> None: + def __init__(self, iterable: Iterable[_T] | None = None) -> None: """ >>> queue1 = Queue() >>> str(queue1) From 953660b868b173828e568255cce79c52daf01bec Mon Sep 17 00:00:00 2001 From: Amirsoroush Date: Sat, 8 Apr 2023 11:32:11 +0300 Subject: [PATCH 6/7] enhance readability in queue_on_two_stacks.py --- data_structures/queue/queue_on_two_stacks.py | 105 +++++++++---------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/data_structures/queue/queue_on_two_stacks.py b/data_structures/queue/queue_on_two_stacks.py index 6395d1695b79..61db2b512136 100644 --- a/data_structures/queue/queue_on_two_stacks.py +++ b/data_structures/queue/queue_on_two_stacks.py @@ -6,34 +6,71 @@ _T = TypeVar("_T") -class Queue(Generic[_T]): +class QueueByTwoStacks(Generic[_T]): def __init__(self, iterable: Iterable[_T] | None = None) -> None: """ - >>> queue1 = Queue() + >>> queue1 = QueueByTwoStacks() >>> str(queue1) - '<[]>' - >>> queue2 = Queue([10, 20, 30]) + 'Queue([])' + >>> queue2 = QueueByTwoStacks([10, 20, 30]) >>> str(queue2) - '<[10, 20, 30]>' - >>> queue3 = Queue((i**2 for i in range(1, 4))) + 'Queue([10, 20, 30])' + >>> queue3 = QueueByTwoStacks((i**2 for i in range(1, 4))) >>> str(queue3) - '<[1, 4, 9]>' + 'Queue([1, 4, 9])' """ self._stack1: list[_T] = [] if iterable is None else list(iterable) self._stack2: list[_T] = [] + def __len__(self) -> int: + """ + >>> queue = QueueByTwoStacks() + >>> for i in range(1, 11): + ... queue.put(i) + ... + >>> len(queue) == 10 + True + >>> for i in range(2): + ... queue.get() + 1 + 2 + >>> len(queue) == 8 + True + """ + + 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]) + """ + + items = self._stack2[::-1] + self._stack1 + return f"Queue({items})" + def put(self, item: _T) -> None: """ Put `item` into the Queue - >>> queue = Queue() + >>> queue = QueueByTwoStacks() >>> queue.put(10) >>> queue.put(20) >>> len(queue) == 2 True >>> str(queue) - '<[10, 20]>' + 'Queue([10, 20])' """ self._stack1.append(item) @@ -42,19 +79,20 @@ def get(self) -> _T: """ Get `item` from the Queue - >>> queue = Queue() + >>> queue = QueueByTwoStacks() >>> for i in (10, 20, 30): ... queue.put(i) - >>> len(queue) - 3 >>> queue.get() 10 + >>> queue.put(40) >>> queue.get() 20 + >>> queue.get() + 30 >>> len(queue) == 1 True >>> queue.get() - 30 + 40 >>> queue.get() Traceback (most recent call last): ... @@ -77,7 +115,7 @@ def size(self) -> int: """ Returns the length of the Queue - >>> queue = Queue() + >>> queue = QueueByTwoStacks() >>> queue.size() 0 >>> queue.put(10) @@ -92,45 +130,6 @@ def size(self) -> int: return len(self) - def __str__(self) -> str: - """ - >>> queue = Queue() - >>> str(queue) - '<[]>' - >>> queue.put(10) - >>> str(queue) - '<[10]>' - >>> queue.put(20) - >>> str(queue) - '<[10, 20]>' - >>> queue.get() - 10 - >>> queue.put(30) - >>> str(queue) == '<[20, 30]>' - True - """ - - return f"<{self._stack2[::-1] + self._stack1}>" - - def __len__(self) -> int: - """ - >>> queue = Queue() - >>> for i in range(1, 11): - ... queue.put(i) - ... - >>> len(queue) == 10 - True - >>> for i in range(2): - ... queue.get() - ... - 1 - 2 - >>> len(queue) == 8 - True - """ - - return len(self._stack1) + len(self._stack2) - if __name__ == "__main__": from doctest import testmod From a8eb743146860950245592141a9a6c2c0ca0dd46 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 8 Apr 2023 13:31:35 +0200 Subject: [PATCH 7/7] Create queue_by_two_stacks.py --- data_structures/queue/queue_by_two_stacks.py | 115 +++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 data_structures/queue/queue_by_two_stacks.py diff --git a/data_structures/queue/queue_by_two_stacks.py b/data_structures/queue/queue_by_two_stacks.py new file mode 100644 index 000000000000..cd62f155a63b --- /dev/null +++ b/data_structures/queue/queue_by_two_stacks.py @@ -0,0 +1,115 @@ +"""Queue implementation using two stacks""" + +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()