如何找到分割总和彼此接近的分割?

时间:2016-10-16 11:23:27

标签: python python-2.7 python-3.x recursion split

我有一个列表是

  

test = [10,20,30,40,50,60,70,80,90,100]

我希望找到分割总和彼此接近的分割数= 3所有可能的组合,并选择总和差异最小的分割。

1 个答案:

答案 0 :(得分:0)

第一个脚本使用双for循环将输入列表拆分为所有可能的列表三元组。对于每个三元组,它计算三元组中每个列表的总和,然后创建一个名为diffs的排序列表,其中包含这些总和的绝对差异。它将由diffs后跟三元组组成的元组保存到名为all_splits的列表中。最后,它排序all_splits,因为all_splits中的每个项目都以diffs开头,所保存的元组按其diffs从最低到最高的顺序排序。

def split_list_test(lst):
    all_splits = []
    for i in range(1, len(lst) - 1):
        for j in range(i + 1, len(lst)):
            splits = [lst[:i], lst[i:j], lst[j:]]
            a, b, c = map(sum, splits)
            diffs = sorted((abs(c-a), abs(c-b), abs(b-a)), reverse=True)
            all_splits.append((diffs, splits))
    all_splits.sort()
    return all_splits

test = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

for row in split_list_test(test):
    print(row)

<强>输出

([60, 40, 20], [[10, 20, 30, 40, 50], [60, 70, 80], [90, 100]])
([60, 40, 20], [[10, 20, 30, 40, 50, 60], [70, 80], [90, 100]])
([140, 110, 30], [[10, 20, 30, 40, 50, 60], [70, 80, 90], [100]])
([140, 120, 20], [[10, 20, 30, 40, 50], [60, 70], [80, 90, 100]])
([160, 90, 70], [[10, 20, 30, 40], [50, 60, 70, 80], [90, 100]])
([170, 90, 80], [[10, 20, 30, 40], [50, 60, 70], [80, 90, 100]])
([180, 110, 70], [[10, 20, 30, 40, 50, 60, 70], [80, 90], [100]])
([200, 110, 90], [[10, 20, 30, 40, 50, 60, 70], [80], [90, 100]])
([200, 140, 60], [[10, 20, 30, 40, 50, 60], [70], [80, 90, 100]])
([200, 150, 50], [[10, 20, 30, 40, 50], [60, 70, 80, 90], [100]])
([210, 160, 50], [[10, 20, 30], [40, 50, 60, 70], [80, 90, 100]])
([240, 130, 110], [[10, 20, 30], [40, 50, 60, 70, 80], [90, 100]])
([240, 220, 20], [[10, 20], [30, 40, 50, 60, 70], [80, 90, 100]])
([240, 230, 10], [[10, 20, 30, 40], [50, 60], [70, 80, 90, 100]])
([250, 250, 0], [[10, 20, 30, 40], [50, 60, 70, 80, 90], [100]])
([260, 260, 0], [[10], [20, 30, 40, 50, 60, 70], [80, 90, 100]])
([270, 260, 10], [[10, 20, 30, 40, 50, 60, 70, 80], [90], [100]])
([280, 190, 90], [[10, 20, 30], [40, 50, 60], [70, 80, 90, 100]])
([280, 190, 90], [[10, 20, 30, 40, 50], [60], [70, 80, 90, 100]])
([300, 160, 140], [[10, 20], [30, 40, 50, 60, 70, 80], [90, 100]])
([310, 160, 150], [[10, 20], [30, 40, 50, 60], [70, 80, 90, 100]])
([330, 190, 140], [[10], [20, 30, 40, 50, 60], [70, 80, 90, 100]])
([330, 290, 40], [[10, 20, 30], [40, 50, 60, 70, 80, 90], [100]])
([340, 180, 160], [[10], [20, 30, 40, 50, 60, 70, 80], [90, 100]])
([340, 310, 30], [[10, 20, 30], [40, 50], [60, 70, 80, 90, 100]])
([350, 300, 50], [[10, 20, 30, 40], [50], [60, 70, 80, 90, 100]])
([370, 280, 90], [[10, 20], [30, 40, 50], [60, 70, 80, 90, 100]])
([390, 260, 130], [[10], [20, 30, 40, 50], [60, 70, 80, 90, 100]])
([390, 320, 70], [[10, 20], [30, 40, 50, 60, 70, 80, 90], [100]])
([410, 390, 20], [[10, 20, 30], [40], [50, 60, 70, 80, 90, 100]])
([420, 380, 40], [[10, 20], [30, 40], [50, 60, 70, 80, 90, 100]])
([430, 340, 90], [[10], [20, 30, 40, 50, 60, 70, 80, 90], [100]])
([440, 360, 80], [[10], [20, 30, 40], [50, 60, 70, 80, 90, 100]])
([460, 460, 0], [[10, 20], [30], [40, 50, 60, 70, 80, 90, 100]])
([480, 440, 40], [[10], [20, 30], [40, 50, 60, 70, 80, 90, 100]])
([510, 500, 10], [[10], [20], [30, 40, 50, 60, 70, 80, 90, 100]])

下一个脚本更紧凑,它只返回一个解决方案。它使用不同的规则来决定最小分割。如果(a, b, c)是三元组中列表的总和,从最低到最高排序,则这些总和的绝对差异为c-ac-bb-a。差异的总和为c-a + c-b + b-a,等于2*(c-a),因此我们可以通过查找具有最小值c-a的分割来找到最小分割(使用此规则)。 / p>

def keyfunc(seq):
    sums = sorted(sum(u) for u in seq)
    return sums[2] - sums[0]

def split_list(lst):
    gen = ([lst[:i], lst[i:j], lst[j:]]
        for i in range(1, len(lst) - 1)
            for j in range(i + 1, len(lst)))
    return min(gen, key=keyfunc)

test = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
print(split_list(test))

<强>输出

[[10, 20, 30, 40, 50], [60, 70, 80], [90, 100]]

如您所见,对于此test列表,此版本提供与上述最小解决方案相同的解决方案。