我在下面有一个脚本,它给出了给定总和最接近的2个值。它还迭代给定总和的列表,并在每次迭代后删除已经使用过的数字。
我需要修改此脚本,使其生成最接近每个总和的必要数量的值,而不是2.脚本需要接受浮点值并且不能重用值。实际上,它需要选择最接近目标的最有效集合,更新集合以移除使用的值,然后继续下一个目标等。。
对于成对它,对于需要3个数字或4个等实际最接近总和的特定用例/集合,它不能很好地工作。我需要这个脚本也能够接受这个脚本当前所做的浮点值。
我们非常感谢任何建议。如果有人知道更好的脚本,请告诉我。
import sys
def find_closese_sum(numbers, target):
start = 0
end = len(numbers) - 1
result = sys.maxint
result_tuple = None
while start < end:
if numbers[start] + numbers[end] == target:
print 0, (numbers[start], numbers[end])
return
elif numbers[start] + numbers[end] > target:
if abs(numbers[start] + numbers[end] - target) < result:
result = abs(numbers[start] + numbers[end] - target)
result_tuple = (numbers[start], numbers[end])
end -= 1
else:
if abs(numbers[start] + numbers[end] - target) < result:
result = abs(numbers[start] + numbers[end] - target)
result_tuple = (numbers[start], numbers[end])
start += 1
for i in result_tuple:
numbers.remove(i)
return result_tuple
if __name__ == "__main__":
target = [14,27,39]
numbers = [1,5,5,10,7,8,11,13,66,34]
print numbers
numbers = sorted(numbers)
for i in target:
result_shown = find_closese_sum(numbers, i)
print result_shown
答案 0 :(得分:0)
我没有看到任何优雅的方式来做到这一点,所以你可能不得不暴力解决方案。制作所有可能的数字子集,求和,并检查哪个最接近目标。它看起来像这样。
from itertools import permutations
def find_closest_sum(numbers, target, n):
permlist = list(permutations(numbers, n))
sumlist = [sum(l) for l in permlist]
maxpos = 0
for i in range(1, len(sumlist)):
if abs(sumlist[i] - target) < abs(sumlist[maxpos]-target):
maxpos = i
return permlist[maxpos]
numbers = [1,5,5,10,7,8,11,13,66,34]
result_shown = find_closest_sum(numbers, 20, 4)
print result_shown
使用排列会使您编写的大量代码变得不必要。
答案 1 :(得分:0)
我的回答是,使用python 3但你应该能够轻松移植它。
from itertools import combinations as c
if __name__ == "__main__":
target = [14,27,39]
numbers = [1,5,5,10,7,8,11,13,66,34]
for combo in range(1,4):
for i in target:
#lambda to find the difference between sum and target
diff = lambda x: abs(sum(x) - i)
#get all unique combinations
combos = {tuple(sorted(c)) for c in c(numbers, combo)}
#sort them
combos = sorted(combos, key = diff)
#get the smallest difference
smallest = diff(combos[0])
#filter out combos larger than the smaller difference
result = [c for c in combos if diff(c) == smallest]
print('results for {}, best combinations are off by {}:'.format(i, smallest))
print(result)
您说您需要排除用于之前结果的数字。要做到这一点,只需从列表中删除它们:
#after print(result), inside the "for i in target" loop
#if you want to exclude all numbers used in all combinations
numbers = [n for n in numbers if n not in [b for a in result for b in a]]
#if you only need to remove the first match
numbers = [n for n in numbers if n not in result[0]]
答案 2 :(得分:0)
import numpy as np
import itertools
def find_closese_sum(numbers, targets):
numbers = numbers[:]
for t in targets:
if not numbers:
break
combs = sum([list(itertools.combinations(numbers, r))
for r in range(1, len(numbers)+1)], [])
sums = np.asarray(list(map(sum, combs)))
bestcomb = combs[np.argmin(np.abs(np.asarray(sums) - t))]
numbers = list(set(numbers).difference(bestcomb))
print("Target: {}, combination: {}".format(t, bestcomb))
In [101]: import numpy as np
...: import itertools
...:
...: def find_closese_sum(numbers, targets):
...: numbers = numbers[:]
...: for t in targets:
...: if not numbers:
...: break
...: combs = sum([list(itertools.combinations(numbers, r))
...: for r in range(1, len(numbers)+1)], [])
...: sums = np.asarray(list(map(sum, combs)))
...: bestcomb = combs[np.argmin(np.abs(np.asarray(sums) - t))]
...: numbers = list(set(numbers).difference(bestcomb))
...: print("Target: {}, combination: {}".format(t, bestcomb))
...:
...: targets = [14,27.,39]
...: numbers = [1.0,5,5,10,7,8,11,13,66,34]
...: find_closese_sum(numbers, targets)
...:
Target: 14, combination: (1.0, 13)
Target: 27.0, combination: (5, 5, 10, 7)
Target: 39, combination: (8, 34)
答案 3 :(得分:-1)
不要让它变得复杂,这是我的方法,试试这个:
import itertools
def finding_closet(ls,target,depth):
closest = []
for i in itertools.combinations(ls, depth):
if sum(i) == target:
return i
else:
closest.append((abs(sum(i) - target), i))
return min(closest)[1]
Test_case 0:
print(finding_closet([1,5,5,10,7,8,11,13,66,34],20,2))
输出:
(7, 13)
Test_case 1:
print(finding_closet([1,5,5,10,7,8,11,13,66,34],20,4))
输出:
(1, 5, 5, 8)
test_case_3:
print(finding_closet([1,5,5,10,7,8,11,13,66,34],20,8))
输出:
(1, 5, 5, 10, 7, 8, 11, 13)