From 0b06bbad79128622e37757443a07ebcdd34f5108 Mon Sep 17 00:00:00 2001 From: Dev Date: Sun, 1 Oct 2023 12:21:55 +0530 Subject: [PATCH 1/6] Make binary tree traversals lazy using generators --- .../binary_tree/binary_tree_traversals.py | 184 +++++++++++------- 1 file changed, 115 insertions(+), 69 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 2afb7604f9c6..29bdb3d7a0b1 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -31,170 +31,216 @@ def make_tree() -> Node | None: return tree -def preorder(root: Node | None) -> list[int]: +def preorder(root: Node | None) -> Sequence[int]: """ - Pre-order traversal visits root node, left subtree, right subtree. - >>> preorder(make_tree()) - [1, 2, 4, 5, 3] + Lazy preorder traversal of a binary tree. + + Args: + root: The root node of the binary tree. + + Yields: + The values of nodes in the tree using lazy traversal. """ - return [root.data, *preorder(root.left), *preorder(root.right)] if root else [] + if not root: + return + yield root.data + yield from preorder(root.left) + yield from preorder(root.right) -def postorder(root: Node | None) -> list[int]: +def postorder(root: Node | None) -> Sequence[int]: """ - Post-order traversal visits left subtree, right subtree, root node. - >>> postorder(make_tree()) - [4, 5, 2, 3, 1] + Lazy post-order traversal of a binary tree. + + Args: + root: The root node of the binary tree. + + Yields: + The values of nodes in the tree using lazy traversal. """ - return postorder(root.left) + postorder(root.right) + [root.data] if root else [] + if not root: + return + yield from postorder(root.left) + yield from postorder(root.right) + yield root.data -def inorder(root: Node | None) -> list[int]: +def inorder(root: Node | None) -> Sequence[int]: """ - In-order traversal visits left subtree, root node, right subtree. - >>> inorder(make_tree()) - [4, 2, 5, 1, 3] + Lazy in-order traversal of a binary tree. + + Args: + root: The root node of the binary tree. + + Yields: + The values of nodes in the tree using lazy traversal. """ - return [*inorder(root.left), root.data, *inorder(root.right)] if root else [] + if not root: + return + yield from inorder(root.left) + yield root.data + yield from inorder(root.right) -def reverse_inorder(root: Node | None) -> list[int]: +def reverse_inorder(root: Node | None) -> Sequence[int]: """ - Reverse in-order traversal visits right subtree, root node, left subtree. - >>> reverse_inorder(make_tree()) - [3, 1, 5, 2, 4] + Lazy reverse in-order traversal of a binary tree. + + Args: + root: The root node of the binary tree. + + Yields: + The values of nodes in the tree using lazy traversal. """ - return ( - [*reverse_inorder(root.right), root.data, *reverse_inorder(root.left)] - if root - else [] - ) + if not root: + return + yield from reverse_inorder(root.right) + yield root.data + yield from reverse_inorder(root.left) def height(root: Node | None) -> int: """ Recursive function for calculating the height of the binary tree. - >>> height(None) - 0 - >>> height(make_tree()) - 3 + + Args: + root: The root node of the binary tree. + + Returns: + The height of the binary tree. """ return (max(height(root.left), height(root.right)) + 1) if root else 0 -def level_order(root: Node | None) -> Sequence[Node | None]: - """ - Returns a list of nodes value from a whole binary tree in Level Order Traverse. - Level Order traverse: Visit nodes of the tree level-by-level. +def level_order(root: Node | None) -> Sequence[int]: """ - output: list[Any] = [] + Lazy level order traversal of a binary tree. + Args: + root: The root node of the binary tree. + + Yields: + The values of nodes in the tree using lazy traversal. + """ if root is None: - return output + return process_queue = deque([root]) while process_queue: node = process_queue.popleft() - output.append(node.data) + yield node.data if node.left: process_queue.append(node.left) if node.right: process_queue.append(node.right) - return output def get_nodes_from_left_to_right( root: Node | None, level: int -) -> Sequence[Node | None]: +) -> Sequence[int]: """ - Returns a list of nodes value from a particular level: - Left to right direction of the binary tree. + Lazy traversal to get nodes from left to right at a particular level of a binary tree. + + Args: + root: The root node of the binary tree. + level: The level at which nodes are retrieved. + + Yields: + The values of nodes at the specified level using lazy traversal. """ - output: list[Any] = [] + if not root: + return def populate_output(root: Node | None, level: int) -> None: if not root: return if level == 1: - output.append(root.data) + yield root.data elif level > 1: - populate_output(root.left, level - 1) - populate_output(root.right, level - 1) + yield from populate_output(root.left, level - 1) + yield from populate_output(root.right, level - 1) - populate_output(root, level) - return output + yield from populate_output(root, level) def get_nodes_from_right_to_left( root: Node | None, level: int -) -> Sequence[Node | None]: +) -> Sequence[int]: """ - Returns a list of nodes value from a particular level: - Right to left direction of the binary tree. + Lazy traversal to get nodes from right to left at a particular level of a binary tree. + + Args: + root: The root node of the binary tree. + level: The level at which nodes are retrieved. + + Yields: + The values of nodes at the specified level using lazy traversal. """ - output: list[Any] = [] + if not root: + return def populate_output(root: Node | None, level: int) -> None: - if root is None: + if not root: return if level == 1: - output.append(root.data) + yield root.data elif level > 1: - populate_output(root.right, level - 1) - populate_output(root.left, level - 1) + yield from populate_output(root.right, level - 1) + yield from populate_output(root.left, level - 1) - populate_output(root, level) - return output + yield from populate_output(root, level) def zigzag(root: Node | None) -> Sequence[Node | None] | list[Any]: """ ZigZag traverse: Returns a list of nodes value from left to right and right to left, alternatively. + + Args: + root: The root node of the binary tree. + + Yields: + The values of nodes in a zigzag order using lazy traversal. """ if root is None: - return [] - - output: list[Sequence[Node | None]] = [] + return flag = 0 height_tree = height(root) for h in range(1, height_tree + 1): if not flag: - output.append(get_nodes_from_left_to_right(root, h)) + yield from get_nodes_from_left_to_right(root, h) flag = 1 else: - output.append(get_nodes_from_right_to_left(root, h)) + yield from get_nodes_from_right_to_left(root, h) flag = 0 - return output - def main() -> None: # Main function for testing. # Create binary tree. root = make_tree() # All Traversals of the binary are as follows: - print(f"In-order Traversal: {inorder(root)}") - print(f"Reverse In-order Traversal: {reverse_inorder(root)}") - print(f"Pre-order Traversal: {preorder(root)}") - print(f"Post-order Traversal: {postorder(root)}", "\n") + print(f"In-order Traversal: {list(inorder(root))}") + print(f"Reverse In-order Traversal: {list(reverse_inorder(root))}") + print(f"Pre-order Traversal: {list(preorder(root))}") + print(f"Post-order Traversal: {list(postorder(root))}", "\n") print(f"Height of Tree: {height(root)}", "\n") print("Complete Level Order Traversal: ") - print(level_order(root), "\n") + print(list(level_order(root)), "\n") print("Level-wise order Traversal: ") for level in range(1, height(root) + 1): - print(f"Level {level}:", get_nodes_from_left_to_right(root, level=level)) + print(f"Level {level}:", list(get_nodes_from_left_to_right(root, level=level))) print("\nZigZag order Traversal: ") - print(zigzag(root)) + print(list(zigzag(root))) if __name__ == "__main__": From 9a6de565abda7785a381f069bcb9d2050b59a705 Mon Sep 17 00:00:00 2001 From: Dev Date: Sun, 1 Oct 2023 13:29:27 +0530 Subject: [PATCH 2/6] Feature: Addition of Minimum Number of Platforms (Greedy Algorithm) --- dynamic_programming/minimum_platforms.py | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 dynamic_programming/minimum_platforms.py diff --git a/dynamic_programming/minimum_platforms.py b/dynamic_programming/minimum_platforms.py new file mode 100644 index 000000000000..fea13115fe15 --- /dev/null +++ b/dynamic_programming/minimum_platforms.py @@ -0,0 +1,38 @@ +def minimum_platforms(arrival, departure): + """ + Calculate the minimum number of platforms required at a railway station. + + :param arrival: List of arrival times of trains + :param departure: List of departure times of trains + :return: Minimum number of platforms required + """ + if not arrival or not departure: + return 0 + + arrival.sort() + departure.sort() + + platforms_needed = 1 + result = 1 + i = 1 + j = 0 + + while i < len(arrival) and j < len(departure): + if arrival[i] <= departure[j]: + platforms_needed += 1 + i += 1 + elif arrival[i] > departure[j]: + platforms_needed -= 1 + j += 1 + + if platforms_needed > result: + result = platforms_needed + + return result + + +# Example usage: +arrival_times = [900, 940, 950, 1100, 1500, 1800] +departure_times = [910, 1200, 1120, 1130, 1900, 2000] + +print("Minimum number of platforms required:", minimum_platforms(arrival_times, departure_times)) From c0d1e56c898ddbfd85c57912e9d8c50a9bbd8873 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 08:04:38 +0000 Subject: [PATCH 3/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/binary_tree/binary_tree_traversals.py | 8 ++------ dynamic_programming/minimum_platforms.py | 5 ++++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 29bdb3d7a0b1..fad1f55157cc 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -137,9 +137,7 @@ def level_order(root: Node | None) -> Sequence[int]: process_queue.append(node.right) -def get_nodes_from_left_to_right( - root: Node | None, level: int -) -> Sequence[int]: +def get_nodes_from_left_to_right(root: Node | None, level: int) -> Sequence[int]: """ Lazy traversal to get nodes from left to right at a particular level of a binary tree. @@ -165,9 +163,7 @@ def populate_output(root: Node | None, level: int) -> None: yield from populate_output(root, level) -def get_nodes_from_right_to_left( - root: Node | None, level: int -) -> Sequence[int]: +def get_nodes_from_right_to_left(root: Node | None, level: int) -> Sequence[int]: """ Lazy traversal to get nodes from right to left at a particular level of a binary tree. diff --git a/dynamic_programming/minimum_platforms.py b/dynamic_programming/minimum_platforms.py index fea13115fe15..b102a69f0415 100644 --- a/dynamic_programming/minimum_platforms.py +++ b/dynamic_programming/minimum_platforms.py @@ -35,4 +35,7 @@ def minimum_platforms(arrival, departure): arrival_times = [900, 940, 950, 1100, 1500, 1800] departure_times = [910, 1200, 1120, 1130, 1900, 2000] -print("Minimum number of platforms required:", minimum_platforms(arrival_times, departure_times)) +print( + "Minimum number of platforms required:", + minimum_platforms(arrival_times, departure_times), +) From b83826ddda457ed3d34f4e36a7470940df0a6cf6 Mon Sep 17 00:00:00 2001 From: Dev Date: Sun, 1 Oct 2023 13:37:23 +0530 Subject: [PATCH 4/6] Feature: Addition of Minimum Number of Platforms (Greedy Algorithm) --- dynamic_programming/minimum_platforms.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dynamic_programming/minimum_platforms.py b/dynamic_programming/minimum_platforms.py index fea13115fe15..d170c6fd0be5 100644 --- a/dynamic_programming/minimum_platforms.py +++ b/dynamic_programming/minimum_platforms.py @@ -1,4 +1,6 @@ -def minimum_platforms(arrival, departure): +from typing import List + +def minimum_platforms(arrival: List[int], departure: List[int]) -> int: """ Calculate the minimum number of platforms required at a railway station. @@ -30,7 +32,6 @@ def minimum_platforms(arrival, departure): return result - # Example usage: arrival_times = [900, 940, 950, 1100, 1500, 1800] departure_times = [910, 1200, 1120, 1130, 1900, 2000] From e9163ed2cd447a5f55bdb7ae09e0f554e7181f2a Mon Sep 17 00:00:00 2001 From: Dev Date: Sun, 1 Oct 2023 13:38:58 +0530 Subject: [PATCH 5/6] Feature: Addition of Minimum Number of Platforms (Greedy Algorithm) --- dynamic_programming/minimum_platforms.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dynamic_programming/minimum_platforms.py b/dynamic_programming/minimum_platforms.py index 7b98517435e0..d170c6fd0be5 100644 --- a/dynamic_programming/minimum_platforms.py +++ b/dynamic_programming/minimum_platforms.py @@ -36,7 +36,4 @@ def minimum_platforms(arrival: List[int], departure: List[int]) -> int: arrival_times = [900, 940, 950, 1100, 1500, 1800] departure_times = [910, 1200, 1120, 1130, 1900, 2000] -print( - "Minimum number of platforms required:", - minimum_platforms(arrival_times, departure_times), -) +print("Minimum number of platforms required:", minimum_platforms(arrival_times, departure_times)) From 4bed322a8a2bc96903e23079ef144ec1383db92f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 08:09:43 +0000 Subject: [PATCH 6/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dynamic_programming/minimum_platforms.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dynamic_programming/minimum_platforms.py b/dynamic_programming/minimum_platforms.py index d170c6fd0be5..a2263e4ed2f1 100644 --- a/dynamic_programming/minimum_platforms.py +++ b/dynamic_programming/minimum_platforms.py @@ -1,5 +1,6 @@ from typing import List + def minimum_platforms(arrival: List[int], departure: List[int]) -> int: """ Calculate the minimum number of platforms required at a railway station. @@ -32,8 +33,12 @@ def minimum_platforms(arrival: List[int], departure: List[int]) -> int: return result + # Example usage: arrival_times = [900, 940, 950, 1100, 1500, 1800] departure_times = [910, 1200, 1120, 1130, 1900, 2000] -print("Minimum number of platforms required:", minimum_platforms(arrival_times, departure_times)) +print( + "Minimum number of platforms required:", + minimum_platforms(arrival_times, departure_times), +)