From 3fec355a8789dda3d347846d1bb37dabc6a338b6 Mon Sep 17 00:00:00 2001 From: parth Date: Thu, 5 Oct 2023 19:34:05 +0530 Subject: [PATCH 01/13] largest divisible subset --- .../largest_divisible_subset.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 dynamic_programming/largest_divisible_subset.py diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py new file mode 100644 index 000000000000..db4ff0d46449 --- /dev/null +++ b/dynamic_programming/largest_divisible_subset.py @@ -0,0 +1,61 @@ +from __future__ import annotations + + +def largest_divisible_subset(array): + """ + Algorithm to find the biggest subset + in the given array such that for any + 2 elements x and y in the subset, + either x divides y or y divides x + >>> largest_divisible_subset([1,16,7,8,4]) + [16, 8, 4, 1] + >>> largest_divisible_subset([1,2,3]) + [2, 1] + >>> largest_divisible_subset([1, 2, 4, 8]) + [8, 4, 2, 1] + """ + n = len(array) + + # Sort the array in ascending order + # as the sequence does not matter + # we only have to pick up a subset + array.sort() + + # Initialize dp and hash arrays with 1s + dp = [1] * n + hash_arr = list(range(n)) + + # Iterate through the array + for i in range(n): + for prev_index in range(i): + if array[i] % array[prev_index] == 0 and 1 + dp[prev_index] > dp[i]: + dp[i] = 1 + dp[prev_index] + hash_arr[i] = prev_index + + ans = -1 + last_index = -1 + + # Find the maximum length and its corresponding index + for i in range(n): + if dp[i] > ans: + ans = dp[i] + last_index = i + + # Reconstruct the divisible subset + result = [array[last_index]] + while hash_arr[last_index] != last_index: + last_index = hash_arr[last_index] + result.append(array[last_index]) + + return result + +if __name__ == "__main__": + from doctest import testmod + + testmod() + + array = [1, 16, 7, 8, 4] + + ans = largest_divisible_subset(array) + + print("The longest divisible subset elements are:", ans) \ No newline at end of file From e96dfb5062bcca01d0cfe1e29d228821608b80db Mon Sep 17 00:00:00 2001 From: parth Date: Thu, 5 Oct 2023 19:41:14 +0530 Subject: [PATCH 02/13] minor tweaks --- .../largest_divisible_subset.py | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index db4ff0d46449..c825b531ba8a 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -1,10 +1,10 @@ from __future__ import annotations -def largest_divisible_subset(array): +def largest_divisible_subset(array: list[int]) -> list[int]: """ - Algorithm to find the biggest subset - in the given array such that for any + Algorithm to find the biggest subset + in the given array such that for any 2 elements x and y in the subset, either x divides y or y divides x >>> largest_divisible_subset([1,16,7,8,4]) @@ -14,41 +14,42 @@ def largest_divisible_subset(array): >>> largest_divisible_subset([1, 2, 4, 8]) [8, 4, 2, 1] """ - n = len(array) + array_size = len(array) # Sort the array in ascending order - # as the sequence does not matter + # as the sequence does not matter # we only have to pick up a subset array.sort() - # Initialize dp and hash arrays with 1s - dp = [1] * n - hash_arr = list(range(n)) + # Initialize memo and hash arrays with 1s + memo = [1] * array_size + hash_array = list(range(array_size)) # Iterate through the array - for i in range(n): + for i in range(array_size): for prev_index in range(i): - if array[i] % array[prev_index] == 0 and 1 + dp[prev_index] > dp[i]: - dp[i] = 1 + dp[prev_index] - hash_arr[i] = prev_index + if array[i] % array[prev_index] == 0 and 1 + memo[prev_index] > memo[i]: + memo[i] = 1 + memo[prev_index] + hash_array[i] = prev_index ans = -1 last_index = -1 # Find the maximum length and its corresponding index - for i in range(n): - if dp[i] > ans: - ans = dp[i] + for i in range(array_size): + if memo[i] > ans: + ans = memo[i] last_index = i # Reconstruct the divisible subset result = [array[last_index]] - while hash_arr[last_index] != last_index: - last_index = hash_arr[last_index] + while hash_array[last_index] != last_index: + last_index = hash_array[last_index] result.append(array[last_index]) return result + if __name__ == "__main__": from doctest import testmod @@ -56,6 +57,6 @@ def largest_divisible_subset(array): array = [1, 16, 7, 8, 4] - ans = largest_divisible_subset(array) + answer = largest_divisible_subset(array) - print("The longest divisible subset elements are:", ans) \ No newline at end of file + print("The longest divisible subset elements are:", answer) From e78e5f6a5a2809caf872db9d8f1fc977f3776c59 Mon Sep 17 00:00:00 2001 From: Parth <100679824+pa-kh039@users.noreply.github.com> Date: Thu, 5 Oct 2023 20:23:57 +0530 Subject: [PATCH 03/13] adding more test cases Co-authored-by: Christian Clauss --- dynamic_programming/largest_divisible_subset.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index c825b531ba8a..55711c9df747 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -7,12 +7,24 @@ def largest_divisible_subset(array: list[int]) -> list[int]: in the given array such that for any 2 elements x and y in the subset, either x divides y or y divides x - >>> largest_divisible_subset([1,16,7,8,4]) + >>> largest_divisible_subset([1, 16, 7, 8, 4]) [16, 8, 4, 1] - >>> largest_divisible_subset([1,2,3]) + >>> largest_divisible_subset([1, 2, 3]) [2, 1] + >>> largest_divisible_subset([-1, -2, -3]) + [-3] >>> largest_divisible_subset([1, 2, 4, 8]) [8, 4, 2, 1] + >>> largest_divisible_subset((1, 2, 4, 8)) + [8, 4, 2, 1] + >>> largest_divisible_subset([1, 1, 1]) + [1, 1, 1] + >>> largest_divisible_subset([0, 0, 0]) + [0, 0, 0] + >>> largest_divisible_subset([-1, -1, -1]) + [-1, -1, -1] + >>> largest_divisible_subset([]) + [] """ array_size = len(array) From 16ff978b34aaf0c59d20f6d17f65dce82b064279 Mon Sep 17 00:00:00 2001 From: Parth <100679824+pa-kh039@users.noreply.github.com> Date: Thu, 5 Oct 2023 20:24:41 +0530 Subject: [PATCH 04/13] improving code for better readability Co-authored-by: Christian Clauss --- dynamic_programming/largest_divisible_subset.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index 55711c9df747..3bfba9d30800 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -38,9 +38,9 @@ def largest_divisible_subset(array: list[int]) -> list[int]: hash_array = list(range(array_size)) # Iterate through the array - for i in range(array_size): + for i, item in enumerate(array): for prev_index in range(i): - if array[i] % array[prev_index] == 0 and 1 + memo[prev_index] > memo[i]: + if item % array[prev_index] == 0 and 1 + memo[prev_index] > memo[i]: memo[i] = 1 + memo[prev_index] hash_array[i] = prev_index From 344a54525fd35dad84906bfc698007deb8b89c86 Mon Sep 17 00:00:00 2001 From: Parth <100679824+pa-kh039@users.noreply.github.com> Date: Thu, 5 Oct 2023 20:25:55 +0530 Subject: [PATCH 05/13] update Co-authored-by: Christian Clauss --- dynamic_programming/largest_divisible_subset.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index 3bfba9d30800..56584cabdfa9 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -48,9 +48,9 @@ def largest_divisible_subset(array: list[int]) -> list[int]: last_index = -1 # Find the maximum length and its corresponding index - for i in range(array_size): - if memo[i] > ans: - ans = memo[i] + for i, memo_item in enumerate(memo): + if memo_item > ans: + ans = memo_item last_index = i # Reconstruct the divisible subset From 46928270dd5ac63fd8b101463195086e126ba7fe Mon Sep 17 00:00:00 2001 From: Parth <100679824+pa-kh039@users.noreply.github.com> Date: Thu, 5 Oct 2023 20:32:29 +0530 Subject: [PATCH 06/13] update Co-authored-by: Christian Clauss --- dynamic_programming/largest_divisible_subset.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index 56584cabdfa9..cbd277e422c4 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -67,7 +67,8 @@ def largest_divisible_subset(array: list[int]) -> list[int]: testmod() - array = [1, 16, 7, 8, 4] + items = [1, 16, 7, 8, 4] + print(f"The longest divisible subset of {items} is {largest_divisible_subset(items)}.") answer = largest_divisible_subset(array) From c8465fda18d77af20473463d52dfe5a3f8c802dc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 5 Oct 2023 15:02:58 +0000 Subject: [PATCH 07/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dynamic_programming/largest_divisible_subset.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index cbd277e422c4..c9fd30528070 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -68,7 +68,9 @@ def largest_divisible_subset(array: list[int]) -> list[int]: testmod() items = [1, 16, 7, 8, 4] - print(f"The longest divisible subset of {items} is {largest_divisible_subset(items)}.") + print( + f"The longest divisible subset of {items} is {largest_divisible_subset(items)}." + ) answer = largest_divisible_subset(array) From 726d94b6dd3f33e8ef28d29f30c4a960db340e6b Mon Sep 17 00:00:00 2001 From: parth Date: Thu, 5 Oct 2023 20:48:48 +0530 Subject: [PATCH 08/13] suggested changes done, and further modfications --- .../largest_divisible_subset.py | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index c9fd30528070..5c61dee8cb02 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -15,7 +15,7 @@ def largest_divisible_subset(array: list[int]) -> list[int]: [-3] >>> largest_divisible_subset([1, 2, 4, 8]) [8, 4, 2, 1] - >>> largest_divisible_subset((1, 2, 4, 8)) + >>> largest_divisible_subset([1, 2, 4, 8]) [8, 4, 2, 1] >>> largest_divisible_subset([1, 1, 1]) [1, 1, 1] @@ -40,7 +40,9 @@ def largest_divisible_subset(array: list[int]) -> list[int]: # Iterate through the array for i, item in enumerate(array): for prev_index in range(i): - if item % array[prev_index] == 0 and 1 + memo[prev_index] > memo[i]: + if ((array[prev_index] != 0 and item % array[prev_index]) == 0) and ( + (1 + memo[prev_index]) > memo[i] + ): memo[i] = 1 + memo[prev_index] hash_array[i] = prev_index @@ -54,6 +56,8 @@ def largest_divisible_subset(array: list[int]) -> list[int]: last_index = i # Reconstruct the divisible subset + if last_index == -1: + return [] result = [array[last_index]] while hash_array[last_index] != last_index: last_index = hash_array[last_index] @@ -71,7 +75,11 @@ def largest_divisible_subset(array: list[int]) -> list[int]: print( f"The longest divisible subset of {items} is {largest_divisible_subset(items)}." ) - - answer = largest_divisible_subset(array) - - print("The longest divisible subset elements are:", answer) + if len(items) == 0: + print("No items to form subset!") + else: + answer = largest_divisible_subset(items) + if len(answer) == 0: + print("No subset found") + else: + print("The longest divisible subset elements are:", answer) From 09fde0e2313a9d8b788653269faba3d725aa9e17 Mon Sep 17 00:00:00 2001 From: parth Date: Thu, 5 Oct 2023 21:02:14 +0530 Subject: [PATCH 09/13] final update --- dynamic_programming/largest_divisible_subset.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index 5c61dee8cb02..5fbe6c639793 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -72,9 +72,7 @@ def largest_divisible_subset(array: list[int]) -> list[int]: testmod() items = [1, 16, 7, 8, 4] - print( - f"The longest divisible subset of {items} is {largest_divisible_subset(items)}." - ) + if len(items) == 0: print("No items to form subset!") else: @@ -82,4 +80,6 @@ def largest_divisible_subset(array: list[int]) -> list[int]: if len(answer) == 0: print("No subset found") else: - print("The longest divisible subset elements are:", answer) + print( + f"The longest divisible subset of {items} is {answer}." + ) From a1bcbd3108b8904ab88f786ddea2d40bf0cf9f08 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 5 Oct 2023 15:34:27 +0000 Subject: [PATCH 10/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dynamic_programming/largest_divisible_subset.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index 5fbe6c639793..e6a4c45dbeba 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -72,7 +72,7 @@ def largest_divisible_subset(array: list[int]) -> list[int]: testmod() items = [1, 16, 7, 8, 4] - + if len(items) == 0: print("No items to form subset!") else: @@ -80,6 +80,4 @@ def largest_divisible_subset(array: list[int]) -> list[int]: if len(answer) == 0: print("No subset found") else: - print( - f"The longest divisible subset of {items} is {answer}." - ) + print(f"The longest divisible subset of {items} is {answer}.") From 9c8b15f17574817793fbc2267e7f5facc89c827e Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 5 Oct 2023 18:13:59 +0200 Subject: [PATCH 11/13] Update largest_divisible_subset.py --- .../largest_divisible_subset.py | 40 ++++++++----------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index e6a4c45dbeba..162d95ee31bd 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -1,7 +1,7 @@ from __future__ import annotations -def largest_divisible_subset(array: list[int]) -> list[int]: +def largest_divisible_subset(items: list[int]) -> list[int]: """ Algorithm to find the biggest subset in the given array such that for any @@ -15,7 +15,7 @@ def largest_divisible_subset(array: list[int]) -> list[int]: [-3] >>> largest_divisible_subset([1, 2, 4, 8]) [8, 4, 2, 1] - >>> largest_divisible_subset([1, 2, 4, 8]) + >>> largest_divisible_subset((1, 2, 4, 8)) [8, 4, 2, 1] >>> largest_divisible_subset([1, 1, 1]) [1, 1, 1] @@ -26,21 +26,21 @@ def largest_divisible_subset(array: list[int]) -> list[int]: >>> largest_divisible_subset([]) [] """ - array_size = len(array) + # Sort the array in ascending order as the sequence does not matter we only have to + # pick up a subset. + items = sorted(items) + + number_of_items = len(items) - # Sort the array in ascending order - # as the sequence does not matter - # we only have to pick up a subset - array.sort() - # Initialize memo and hash arrays with 1s - memo = [1] * array_size - hash_array = list(range(array_size)) + # Initialize memo with 1s and hash with increasing numbers + memo = [1] * number_of_items + hash_array = list(range(number_of_items)) # Iterate through the array - for i, item in enumerate(array): + for i, item in enumerate(items): for prev_index in range(i): - if ((array[prev_index] != 0 and item % array[prev_index]) == 0) and ( + if ((items[prev_index] != 0 and item % items[prev_index]) == 0) and ( (1 + memo[prev_index]) > memo[i] ): memo[i] = 1 + memo[prev_index] @@ -58,10 +58,10 @@ def largest_divisible_subset(array: list[int]) -> list[int]: # Reconstruct the divisible subset if last_index == -1: return [] - result = [array[last_index]] + result = [items[last_index]] while hash_array[last_index] != last_index: last_index = hash_array[last_index] - result.append(array[last_index]) + result.append(items[last_index]) return result @@ -72,12 +72,6 @@ def largest_divisible_subset(array: list[int]) -> list[int]: testmod() items = [1, 16, 7, 8, 4] - - if len(items) == 0: - print("No items to form subset!") - else: - answer = largest_divisible_subset(items) - if len(answer) == 0: - print("No subset found") - else: - print(f"The longest divisible subset of {items} is {answer}.") + print( + f"The longest divisible subset of {items} is {largest_divisible_subset(items)}." + ) From 4cf3f070bab05e482a7beb3016e7cd265b39a88d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 5 Oct 2023 16:14:59 +0000 Subject: [PATCH 12/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dynamic_programming/largest_divisible_subset.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index 162d95ee31bd..5d2d48d72d03 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -32,7 +32,6 @@ def largest_divisible_subset(items: list[int]) -> list[int]: number_of_items = len(items) - # Initialize memo with 1s and hash with increasing numbers memo = [1] * number_of_items hash_array = list(range(number_of_items)) From 8d47a8acacad5da173babbdcc50b287b93925cb5 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 5 Oct 2023 18:16:38 +0200 Subject: [PATCH 13/13] Update largest_divisible_subset.py --- dynamic_programming/largest_divisible_subset.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py index 5d2d48d72d03..db38636e29db 100644 --- a/dynamic_programming/largest_divisible_subset.py +++ b/dynamic_programming/largest_divisible_subset.py @@ -3,10 +3,8 @@ def largest_divisible_subset(items: list[int]) -> list[int]: """ - Algorithm to find the biggest subset - in the given array such that for any - 2 elements x and y in the subset, - either x divides y or y divides x + Algorithm to find the biggest subset in the given array such that for any 2 elements + x and y in the subset, either x divides y or y divides x. >>> largest_divisible_subset([1, 16, 7, 8, 4]) [16, 8, 4, 1] >>> largest_divisible_subset([1, 2, 3])