From 836a8d0029de5b44f74a16d68b664f7dc2b529c1 Mon Sep 17 00:00:00 2001 From: Aditya Kumar Mishra <154746713+adityakrmishra@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:20:54 +0530 Subject: [PATCH 1/4] Optimized Recursive Knapsack with Memoization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added memoization to avoid redundant calculations - Improved function readability with better parameter naming - Ensured correct handling of empty inputs - Reduced time complexity from O(2ⁿ) to O(n * max_weight) --- knapsack/recursive_approach_knapsack.py | 72 ++++++++++++++----------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/knapsack/recursive_approach_knapsack.py b/knapsack/recursive_approach_knapsack.py index 9a8ed1886a5b..5eb76067e5e6 100644 --- a/knapsack/recursive_approach_knapsack.py +++ b/knapsack/recursive_approach_knapsack.py @@ -1,51 +1,61 @@ -# To get an insight into naive recursive way to solve the Knapsack problem - - """ A shopkeeper has bags of wheat that each have different weights and different profits. -eg. -no_of_items 4 -profit 5 4 8 6 -weight 1 2 4 5 -max_weight 5 +Example: +no_of_items = 4 +profit = [5, 4, 8, 6] +weight = [1, 2, 4, 5] +max_weight = 5 + Constraints: -max_weight > 0 -profit[i] >= 0 -weight[i] >= 0 -Calculate the maximum profit that the shopkeeper can make given maxmum weight that can -be carried. +- max_weight > 0 +- profit[i] >= 0 +- weight[i] >= 0 + +Calculate the maximum profit the shopkeeper can make given the maximum weight that can be carried. """ +from functools import lru_cache -def knapsack( - weights: list, values: list, number_of_items: int, max_weight: int, index: int -) -> int: +def knapsack(weights: list, values: list, number_of_items: int, max_weight: int, index: int, memo=None) -> int: """ - Function description is as follows- - :param weights: Take a list of weights - :param values: Take a list of profits corresponding to the weights - :param number_of_items: number of items available to pick from - :param max_weight: Maximum weight that could be carried - :param index: the element we are looking at - :return: Maximum expected gain + Optimized Recursive Knapsack with Memoization. + + :param weights: List of item weights + :param values: List of corresponding item profits + :param number_of_items: Total number of available items + :param max_weight: Maximum weight capacity of the knapsack + :param index: Current item index being considered + :param memo: Dictionary to store computed results for optimization + :return: Maximum profit possible + >>> knapsack([1, 2, 4, 5], [5, 4, 8, 6], 4, 5, 0) 13 - >>> knapsack([3 ,4 , 5], [10, 9 , 8], 3, 25, 0) + >>> knapsack([3, 4, 5], [10, 9, 8], 3, 25, 0) 27 """ if index == number_of_items: return 0 - ans1 = 0 + + if memo is None: + memo = {} + + # If already computed, return stored value + if (index, max_weight) in memo: + return memo[(index, max_weight)] + + # Case 1: Skip the current item + ans1 = knapsack(weights, values, number_of_items, max_weight, index + 1, memo) + + # Case 2: Include the current item (if weight allows) ans2 = 0 - ans1 = knapsack(weights, values, number_of_items, max_weight, index + 1) if weights[index] <= max_weight: - ans2 = values[index] + knapsack( - weights, values, number_of_items, max_weight - weights[index], index + 1 - ) - return max(ans1, ans2) + ans2 = values[index] + knapsack(weights, values, number_of_items, max_weight - weights[index], index + 1, memo) + + # Store and return the maximum value obtained + memo[(index, max_weight)] = max(ans1, ans2) + return memo[(index, max_weight)] if __name__ == "__main__": import doctest - doctest.testmod() From ecc89b537bd17493758f06b3dc34b8af9aa42ce3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 31 Jan 2025 11:03:43 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- knapsack/recursive_approach_knapsack.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/knapsack/recursive_approach_knapsack.py b/knapsack/recursive_approach_knapsack.py index 5eb76067e5e6..43f0fe8a3de3 100644 --- a/knapsack/recursive_approach_knapsack.py +++ b/knapsack/recursive_approach_knapsack.py @@ -16,7 +16,15 @@ from functools import lru_cache -def knapsack(weights: list, values: list, number_of_items: int, max_weight: int, index: int, memo=None) -> int: + +def knapsack( + weights: list, + values: list, + number_of_items: int, + max_weight: int, + index: int, + memo=None, +) -> int: """ Optimized Recursive Knapsack with Memoization. @@ -49,7 +57,14 @@ def knapsack(weights: list, values: list, number_of_items: int, max_weight: int, # Case 2: Include the current item (if weight allows) ans2 = 0 if weights[index] <= max_weight: - ans2 = values[index] + knapsack(weights, values, number_of_items, max_weight - weights[index], index + 1, memo) + ans2 = values[index] + knapsack( + weights, + values, + number_of_items, + max_weight - weights[index], + index + 1, + memo, + ) # Store and return the maximum value obtained memo[(index, max_weight)] = max(ans1, ans2) @@ -58,4 +73,5 @@ def knapsack(weights: list, values: list, number_of_items: int, max_weight: int, if __name__ == "__main__": import doctest + doctest.testmod() From 8da5b0a9b618cdf50c3d1d8d0c7a213917321a24 Mon Sep 17 00:00:00 2001 From: Aditya Kumar Mishra <154746713+adityakrmishra@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:43:30 +0530 Subject: [PATCH 3/4] Fix linting errors (E501, F401) in recursive knapsack implementation --- knapsack/recursive_approach_knapsack.py | 66 ++++++++----------------- 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/knapsack/recursive_approach_knapsack.py b/knapsack/recursive_approach_knapsack.py index 43f0fe8a3de3..6a7c284952cc 100644 --- a/knapsack/recursive_approach_knapsack.py +++ b/knapsack/recursive_approach_knapsack.py @@ -1,40 +1,31 @@ """ A shopkeeper has bags of wheat that each have different weights and different profits. Example: -no_of_items = 4 -profit = [5, 4, 8, 6] -weight = [1, 2, 4, 5] -max_weight = 5 + no_of_items = 4 + profit = [5, 4, 8, 6] + weight = [1, 2, 4, 5] + max_weight = 5 Constraints: -- max_weight > 0 -- profit[i] >= 0 -- weight[i] >= 0 + max_weight > 0 + profit[i] >= 0 + weight[i] >= 0 -Calculate the maximum profit the shopkeeper can make given the maximum weight that can be carried. +Calculate the maximum profit the shopkeeper can make given the maximum weight +that can be carried. """ -from functools import lru_cache - - def knapsack( - weights: list, - values: list, - number_of_items: int, - max_weight: int, - index: int, - memo=None, + weights: list, values: list, number_of_items: int, max_weight: int, index: int ) -> int: """ - Optimized Recursive Knapsack with Memoization. - + Function description is as follows: :param weights: List of item weights - :param values: List of corresponding item profits - :param number_of_items: Total number of available items - :param max_weight: Maximum weight capacity of the knapsack - :param index: Current item index being considered - :param memo: Dictionary to store computed results for optimization - :return: Maximum profit possible + :param values: List of item profits corresponding to the weights + :param number_of_items: Number of available items + :param max_weight: Maximum weight that can be carried + :param index: The item index currently being checked + :return: Maximum expected gain >>> knapsack([1, 2, 4, 5], [5, 4, 8, 6], 4, 5, 0) 13 @@ -44,31 +35,14 @@ def knapsack( if index == number_of_items: return 0 - if memo is None: - memo = {} - - # If already computed, return stored value - if (index, max_weight) in memo: - return memo[(index, max_weight)] - - # Case 1: Skip the current item - ans1 = knapsack(weights, values, number_of_items, max_weight, index + 1, memo) - - # Case 2: Include the current item (if weight allows) + ans1 = knapsack(weights, values, number_of_items, max_weight, index + 1) ans2 = 0 if weights[index] <= max_weight: ans2 = values[index] + knapsack( - weights, - values, - number_of_items, - max_weight - weights[index], - index + 1, - memo, + weights, values, number_of_items, max_weight - weights[index], index + 1 ) - - # Store and return the maximum value obtained - memo[(index, max_weight)] = max(ans1, ans2) - return memo[(index, max_weight)] + + return max(ans1, ans2) if __name__ == "__main__": From a70d456274b25d454f9992767939f68355ab1b77 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 31 Jan 2025 11:13:54 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- knapsack/recursive_approach_knapsack.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/knapsack/recursive_approach_knapsack.py b/knapsack/recursive_approach_knapsack.py index 6a7c284952cc..822583df035c 100644 --- a/knapsack/recursive_approach_knapsack.py +++ b/knapsack/recursive_approach_knapsack.py @@ -11,10 +11,11 @@ profit[i] >= 0 weight[i] >= 0 -Calculate the maximum profit the shopkeeper can make given the maximum weight +Calculate the maximum profit the shopkeeper can make given the maximum weight that can be carried. """ + def knapsack( weights: list, values: list, number_of_items: int, max_weight: int, index: int ) -> int: @@ -41,7 +42,7 @@ def knapsack( ans2 = values[index] + knapsack( weights, values, number_of_items, max_weight - weights[index], index + 1 ) - + return max(ans1, ans2)