问题
I am programming a knapsack encryption algorithm. I am new to Python programming. I have a list and an integer value I have determined. I want to find what elements in my list will sum up to my integer value. I can get it running for two elements or less but I can not run it for more than two elements.
Assume:
privkey = [2,3,6,13,27,52]
cipher = 9
My current function can run the scenario above:
searchList = []
for i, number in enumerate(privkey[:-1]):
complementary = cipher - number
if complementary in privkey[i+1:]:
searchList.append(number)
searchList.append(complementary)
print("Solution Found: {} and {}".format(number, complementary))
break
else:
print("No solutions exist")
print(searchList)
The expected output of this will be [3,6] and indeed works.
However if cipher is changed to a condition which requires the sum of more than three characters for example:
cipher = 11
This would require the sum of privkey[0]+privkey[1]+privkey[2].
How can I create a code that covers these bases as well?
回答1:
You can use this code (For python3). This code will provide you all possible combinations from privkey list which satisfy the cipher integer.
from itertools import combinations
privkey = [2,3,6,13,27,52]
cipher = 9
character = 2 # change it to get sum of dynamic no. of character
possible_combination = list(combinations(privkey, character))
li =[each for each in possible_combination if sum(each) == cipher]
if li:
print("List-> ", *li)
else:
print("No combination found from privkey list to satisfy the cipher integer.")
OUTPUT:
(3, 6)
回答2:
It needs to be done recursively. This is the function I built, it may not be optimized:
def find_sum(my_list, left_list, target):
if sum(my_list) == target:
return my_list
# Add this condition if all the numbers are positive (e.g once you are over the target, don't continue to try numbers
if sum(my_list) > target:
return
if len(left_list) == 0:
return
for i in range(len(left_list)):
current_number = left_list.pop(0)
my_list.append(current_number)
result = find_sum(my_list, left_list, target)
if result:
return result
my_list.pop()
left_list.append(current_number)
return
privkey = [2,3,6,13,27,52]
cipher = 11
print(find_sum([], privkey, cipher))
Output:
[2, 3, 6]
Or a solution based on @Shivam Gupta's method, but that checks for all the possible number of items possible:
from itertools import combinations
privkey = [2,3,6,13,27,52]
cipher = 11
for character in range(1, len(privkey) + 1):
possible_combination = list(combinations(privkey, character))
li =[each for each in possible_combination if sum(each) == cipher]
if li:
print("List-> ", *li)
break
else: # Will happen only if the loop ended with no match
print("No combination found from privkey list to satisfy the cipher integer.")
Output:
List-> (2, 3, 6)
回答3:
You are on the right track with what you have. The problem is with complementary. If you wanted to do this approach you would need to implement a recursive solution in order to continuously decrement that value.
This solution is much easier to read. I'm not sure if it is the fastest solution but it is easy to understand. Basically instead of going through each list item 1 by 1 and trying to see if anything matches. Just get a list of all the possible combinations and filter out the ones that do not add up to expected result.
from itertools import combinations
privkey = [2,3,6,13,27,52]
cipher = 9
# Get All Possible Combinations Of Numbers In List
combinations = sum([list(
map(list, combinations(privkey, i)))
for i in range(len(privkey) + 1)], [])
# Check If Any Combinations Sum To Cipher
solutions = [x for x in combinations if sum(x) == cipher)]
# Print Solutions
for i in solutions:
print("Solution Found: {0}".format(i)
回答4:
It seems you need to find the sub-array sum. A simple solution is to consider all subarrays one by one and check the sum of every subarray. If you find interesting then Refer Here: Find the subarray with given sum
Hope it will helps : )
来源:https://stackoverflow.com/questions/59064067/how-to-find-what-values-of-a-list-sum-to-a-specified-value