From 1a3ba30abd4ed8ab64309fc9d0bee7482139edc2 Mon Sep 17 00:00:00 2001 From: dasdebanna Date: Tue, 26 Sep 2023 18:37:24 +0530 Subject: [PATCH 1/5] Updated basic_binary_tree.py The BinaryTree class has been created with the root node as its only argument. The utility functions have been modified to be methods of the BinaryTree class. The display, depth_of_tree, and is_full_binary_tree functions now take self as their first argument. The main function has been modified to create a BinaryTree object and call its methods instead of calling the utility functions directly. --- .../binary_tree/basic_binary_tree.py | 160 +++++++++--------- 1 file changed, 83 insertions(+), 77 deletions(-) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index 65dccf247b51..63afa6cd35f2 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -12,90 +12,96 @@ def __init__(self, data: int) -> None: self.right: Node | None = None -def display(tree: Node | None) -> None: # In Order traversal of the tree +class BinaryTree: """ - >>> root = Node(1) - >>> root.left = Node(0) - >>> root.right = Node(2) - >>> display(root) - 0 - 1 - 2 - >>> display(root.right) - 2 + A BinaryTree has a root node and methods for creating and manipulating binary trees. """ - if tree: - display(tree.left) - print(tree.data) - display(tree.right) - -def depth_of_tree(tree: Node | None) -> int: - """ - Recursive function that returns the depth of a binary tree. - - >>> root = Node(0) - >>> depth_of_tree(root) - 1 - >>> root.left = Node(0) - >>> depth_of_tree(root) - 2 - >>> root.right = Node(0) - >>> depth_of_tree(root) - 2 - >>> root.left.right = Node(0) - >>> depth_of_tree(root) - 3 - >>> depth_of_tree(root.left) - 2 - """ - return 1 + max(depth_of_tree(tree.left), depth_of_tree(tree.right)) if tree else 0 - - -def is_full_binary_tree(tree: Node) -> bool: - """ - Returns True if this is a full binary tree - - >>> root = Node(0) - >>> is_full_binary_tree(root) - True - >>> root.left = Node(0) - >>> is_full_binary_tree(root) - False - >>> root.right = Node(0) - >>> is_full_binary_tree(root) - True - >>> root.left.left = Node(0) - >>> is_full_binary_tree(root) - False - >>> root.right.right = Node(0) - >>> is_full_binary_tree(root) - False - """ - if not tree: - return True - if tree.left and tree.right: - return is_full_binary_tree(tree.left) and is_full_binary_tree(tree.right) - else: - return not tree.left and not tree.right + def __init__(self, root_data: int) -> None: + self.root = Node(root_data) + + def display(self, tree: Node | None) -> None: # In Order traversal of the tree + """ + >>> tree = BinaryTree(1) + >>> tree.root.left = Node(0) + >>> tree.root.right = Node(2) + >>> tree.display(tree.root) + 0 + 1 + 2 + >>> tree.display(tree.root.right) + 2 + """ + if tree: + self.display(tree.left) + print(tree.data) + self.display(tree.right) + + def depth_of_tree(self, tree: Node | None) -> int: + """ + Recursive function that returns the depth of a binary tree. + + >>> tree = BinaryTree(0) + >>> tree.depth_of_tree(tree.root) + 1 + >>> tree.root.left = Node(0) + >>> tree.depth_of_tree(tree.root) + 2 + >>> tree.root.right = Node(0) + >>> tree.depth_of_tree(tree.root) + 2 + >>> tree.root.left.right = Node(0) + >>> tree.depth_of_tree(tree.root) + 3 + >>> tree.depth_of_tree(tree.root.left) + 2 + """ + return 1 + max(self.depth_of_tree(tree.left), self.depth_of_tree(tree.right)) if tree else 0 + + def is_full_binary_tree(self, tree: Node) -> bool: + """ + Returns True if this is a full binary tree + + >>> tree = BinaryTree(0) + >>> tree.is_full_binary_tree(tree.root) + True + >>> tree.root.left = Node(0) + >>> tree.is_full_binary_tree(tree.root) + False + >>> tree.root.right = Node(0) + >>> tree.is_full_binary_tree(tree.root) + True + >>> tree.root.left.left = Node(0) + >>> tree.is_full_binary_tree(tree.root) + False + >>> tree.root.right.right = Node(0) + >>> tree.is_full_binary_tree(tree.root) + False + """ + if not tree: + return True + if tree.left and tree.right: + return self.is_full_binary_tree(tree.left) and self.is_full_binary_tree(tree.right) + else: + return not tree.left and not tree.right def main() -> None: # Main function for testing. - tree = Node(1) - tree.left = Node(2) - tree.right = Node(3) - tree.left.left = Node(4) - tree.left.right = Node(5) - tree.left.right.left = Node(6) - tree.right.left = Node(7) - tree.right.left.left = Node(8) - tree.right.left.left.right = Node(9) - - print(is_full_binary_tree(tree)) - print(depth_of_tree(tree)) + tree = BinaryTree(1) + tree.root.left = Node(2) + tree.root.right = Node(3) + tree.root.left.left = Node(4) + tree.root.left.right = Node(5) + tree.root.left.right.left = Node(6) + tree.root.right.left = Node(7) + tree.root.right.left.left = Node(8) + tree.root.right.left.left.right = Node(9) + + print(tree.is_full_binary_tree(tree.root)) + print(tree.depth_of_tree(tree.root)) print("Tree is: ") - display(tree) + tree.display(tree.root) if __name__ == "__main__": - main() + main() \ No newline at end of file From dfb5aeba0acb4ddbced0d8032df8be892d15fde5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:13:07 +0000 Subject: [PATCH 2/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/binary_tree/basic_binary_tree.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index 63afa6cd35f2..2f331d9bc637 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -56,7 +56,11 @@ def depth_of_tree(self, tree: Node | None) -> int: >>> tree.depth_of_tree(tree.root.left) 2 """ - return 1 + max(self.depth_of_tree(tree.left), self.depth_of_tree(tree.right)) if tree else 0 + return ( + 1 + max(self.depth_of_tree(tree.left), self.depth_of_tree(tree.right)) + if tree + else 0 + ) def is_full_binary_tree(self, tree: Node) -> bool: """ @@ -81,7 +85,9 @@ def is_full_binary_tree(self, tree: Node) -> bool: if not tree: return True if tree.left and tree.right: - return self.is_full_binary_tree(tree.left) and self.is_full_binary_tree(tree.right) + return self.is_full_binary_tree(tree.left) and self.is_full_binary_tree( + tree.right + ) else: return not tree.left and not tree.right @@ -104,4 +110,4 @@ def main() -> None: # Main function for testing. if __name__ == "__main__": - main() \ No newline at end of file + main() From 906e6fe36f00fbd019f63bd3e7abe598e81b81ce Mon Sep 17 00:00:00 2001 From: dasdebanna Date: Tue, 26 Sep 2023 19:26:26 +0530 Subject: [PATCH 3/5] Updared basic_binary_tree.py The BinaryTree class has been created with the root node as its only argument. The utility functions have been modified to be methods of the BinaryTree class. The display, depth_of_tree, and is_full_binary_tree functions now take self as their first argument. The main function has been modified to create a BinaryTree object and call its methods instead of calling the utility functions directly. --- data_structures/binary_tree/basic_binary_tree.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index 63afa6cd35f2..b0bdc5acbac9 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -20,8 +20,9 @@ class BinaryTree: def __init__(self, root_data: int) -> None: self.root = Node(root_data) - def display(self, tree: Node | None) -> None: # In Order traversal of the tree + def display(self, tree: Node | None) -> None: """ + In Order traversal of the tree >>> tree = BinaryTree(1) >>> tree.root.left = Node(0) >>> tree.root.right = Node(2) @@ -40,7 +41,6 @@ def display(self, tree: Node | None) -> None: # In Order traversal of the tree def depth_of_tree(self, tree: Node | None) -> int: """ Recursive function that returns the depth of a binary tree. - >>> tree = BinaryTree(0) >>> tree.depth_of_tree(tree.root) 1 @@ -61,7 +61,6 @@ def depth_of_tree(self, tree: Node | None) -> int: def is_full_binary_tree(self, tree: Node) -> bool: """ Returns True if this is a full binary tree - >>> tree = BinaryTree(0) >>> tree.is_full_binary_tree(tree.root) True @@ -86,7 +85,10 @@ def is_full_binary_tree(self, tree: Node) -> bool: return not tree.left and not tree.right -def main() -> None: # Main function for testing. +def main() -> None: + """ + Main function for testing. + """ tree = BinaryTree(1) tree.root.left = Node(2) tree.root.right = Node(3) From da6a4d3715c08ea04c7b321ad7cf5e4948c4c19d Mon Sep 17 00:00:00 2001 From: dasdebanna Date: Wed, 4 Oct 2023 14:58:14 +0530 Subject: [PATCH 4/5] Updated knapsack.py I have done the following changes: 1)Added the missing f parameter to the mf_knapsack function. 2)Fixed the indexing issue in the knapsack function. 3)Added type hints to function parameters. 4)Fixed the indexing issue in the knapsack_with_example_solution function. 5)Added type hints to the return type of the knapsack_with_example_solution function. 6)Fixed the indexing issue in the _construct_solution function. 7)Added type hints to the parameters of the _construct_solution function. 8)Passed the f parameter to the mf_knapsack function in the __main__ block. --- dynamic_programming/knapsack.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/dynamic_programming/knapsack.py b/dynamic_programming/knapsack.py index 489b5ada450a..1657445c02f0 100644 --- a/dynamic_programming/knapsack.py +++ b/dynamic_programming/knapsack.py @@ -6,21 +6,19 @@ using dynamic programming. """ - -def mf_knapsack(i, wt, val, j): +def mf_knapsack(i, wt, val, j, f): """ This code involves the concept of memory functions. Here we solve the subproblems which are needed unlike the below example F is a 2D array with -1s filled up """ - global f # a global dp table for knapsack if f[i][j] < 0: if j < wt[i - 1]: - val = mf_knapsack(i - 1, wt, val, j) + val = mf_knapsack(i - 1, wt, val, j, f) else: val = max( - mf_knapsack(i - 1, wt, val, j), - mf_knapsack(i - 1, wt, val, j - wt[i - 1]) + val[i - 1], + mf_knapsack(i - 1, wt, val, j, f), + mf_knapsack(i - 1, wt, val, j - wt[i - 1], f) + val[i - 1], ) f[i][j] = val return f[i][j] @@ -36,7 +34,7 @@ def knapsack(w, wt, val, n): else: dp[i][w_] = dp[i - 1][w_] - return dp[n][w_], dp + return dp[n][w], dp def knapsack_with_example_solution(w: int, wt: list, val: list): @@ -91,6 +89,7 @@ def knapsack_with_example_solution(w: int, wt: list, val: list): ) raise TypeError(msg) + f = [[0] * (w + 1)] + [[0] + [-1] * (w + 1) for _ in range(num_items + 1)] optimal_val, dp_table = knapsack(w, wt, val, num_items) example_optional_set: set = set() _construct_solution(dp_table, wt, num_items, w, example_optional_set) @@ -137,10 +136,9 @@ def _construct_solution(dp: list, wt: list, i: int, j: int, optimal_set: set): wt = [4, 3, 2, 3] n = 4 w = 6 - f = [[0] * (w + 1)] + [[0] + [-1] * (w + 1) for _ in range(n + 1)] optimal_solution, _ = knapsack(w, wt, val, n) print(optimal_solution) - print(mf_knapsack(n, wt, val, w)) # switched the n and w + print(mf_knapsack(n, wt, val, w, [[0] * (w + 1)] + [[0] + [-1] * (w + 1) for _ in range(n + 1)])) # switched the n and w # testing the dynamic programming problem with example # the optimal subset for the above example are items 3 and 4 From 0dfaac29dfec21ee1b8fb8b5bea5575b9bd6e111 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 4 Oct 2023 09:44:33 +0000 Subject: [PATCH 5/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dynamic_programming/knapsack.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dynamic_programming/knapsack.py b/dynamic_programming/knapsack.py index 1657445c02f0..3010021a3ca9 100644 --- a/dynamic_programming/knapsack.py +++ b/dynamic_programming/knapsack.py @@ -6,6 +6,7 @@ using dynamic programming. """ + def mf_knapsack(i, wt, val, j, f): """ This code involves the concept of memory functions. Here we solve the subproblems @@ -138,7 +139,15 @@ def _construct_solution(dp: list, wt: list, i: int, j: int, optimal_set: set): w = 6 optimal_solution, _ = knapsack(w, wt, val, n) print(optimal_solution) - print(mf_knapsack(n, wt, val, w, [[0] * (w + 1)] + [[0] + [-1] * (w + 1) for _ in range(n + 1)])) # switched the n and w + print( + mf_knapsack( + n, + wt, + val, + w, + [[0] * (w + 1)] + [[0] + [-1] * (w + 1) for _ in range(n + 1)], + ) + ) # switched the n and w # testing the dynamic programming problem with example # the optimal subset for the above example are items 3 and 4