如何求和直到最大高度?

时间:2019-02-12 10:23:57

标签: python for-loop if-statement sum

有一个高度表,总计1743厘米。我有6个单元格,我想将此数字放入单元格中。最大高度为300厘米。我使用for循环,它将在高度列表内取数字,然后加上它们直到更接近300厘米

height=[67, 67, 55, 65, 65, 65, 61, 58, 40, 40, 58, 53, 59, 63, 51, 57, 43, 65, 45, 65, 61, 58, 47, 58, 65, 74, 64, 28, 61, 46, 39]

max_height=300 #cm 

sum1=0
count=0

for i in height:
 sum1=height[count]+sum1

 count+=1
 if max_height>=sum1>=250:

    print(sum1)
    sum1=0
print(sum1)
print("\n",sum(height))

我希望它将得到6个总和,但是得到7个总和。 如果您跑步,将会看到(254,289,273,261,289,292,85)

6 个答案:

答案 0 :(得分:1)

这不是完整的解决方案,但我希望它能为您提供帮助,主要思想是找到最接近的值以生成总和300

height = [67, 67, 55, 65, 65, 65, 61, 58, 40, 40, 58, 53, 59, 63, 51, 57, 43, 65, 45, 65, 61, 58, 47, 58, 65, 74, 64, 28, 61, 46, 39]
elems = [height.pop(0)]
groups = []
while height:
    while sum(elems) <= 300:
        next_el = 0
        for elem in height:
            if sum(elems) + elem <= 300 and elem > next_el:
                next_el = elem
        if next_el:
            elems.append(height.pop(height.index(next_el)))
        else:
            print(sum(elems))
            print(elems)
            groups.append(elems)
            elems = []
            break

print('Total: ', sum([sum(x) for x in groups]))

我的结果是:

273
[67, 74, 67, 65]
300
[65, 65, 65, 65, 40]
300
[65, 64, 63, 61, 47]
297
[61, 61, 59, 58, 58]
281
[58, 58, 57, 55, 53]
292
[51, 46, 45, 43, 40, 39, 28]
Total:  1743

答案 1 :(得分:1)

您要解决的问题在计算上很复杂。它看起来像Knapsack problem的变体。这是一种贪婪的方法,但速度很快。因为它很贪婪,所以如果存在某个解决方案,它可能会找不到。

例如最大高度为300的[120, 120, 100, 80, 65, 65]的最小解为[[120, 100, 80], [120, 65, 65]],但是此算法无法找到它,而是返回了[[120, 120], [100, 80, 65], [65]]

height=[67, 67, 55, 65, 65, 65, 61, 58, 40, 40, 58, 53, 59, 63, 51, 57, 43, 65, 45, 
    65, 61, 58, 47, 58, 65, 74, 64, 28, 61, 46, 39]
max_height=300 #cm 


heights = sorted(height, reverse=True)
groups = []

while heights:
    # whilst there are still items in heights, create a new group of heights
    # with sum no more than 300.
    group = []

    # greedily fill up each group with largest possible values that can fit
    for h in heights:
        if sum(group) + h <= 300:
            group.append(h)

    # remove the values in the group from the list of candidate heights
    for g in group:
        heights.remove(g)

    groups.append(tuple(group))

# output
for g in groups:
    print(g, '->', sum(g))

给予:

(74, 67, 67, 65) -> 273
(65, 65, 65, 65, 40) -> 300
(65, 64, 63, 61, 47) -> 300
(61, 61, 59, 58, 58) -> 297
(58, 58, 57, 55, 53) -> 281
(51, 46, 45, 43, 40, 39, 28) -> 292

请注意,就其接近极限而言,发现的第一组实际上是最差的。这可以追溯到该算法贪婪而不是总是以最少的组数找到解决方案的初始点。

答案 2 :(得分:0)

这是一个算法问题。 这里的问题似乎是,如果您一次填充一个单元格,那么可能不适合最新单元格的值可能仍适合先前的单元格。因此,您没有充分利用每个单元格的大小,例如,您的第一个单元格仅包含254,这意味着您可以在其中容纳整整46 cms的厘米(在列表的后面显示)。

要解决该问题,您实际上需要为单元格创建一个表示(list和/或计数器,尽管您始终可以创建列表的sum ...),然后重新访问单元格检查更多数据是否适合。

答案 3 :(得分:0)

您需要找到长度为6个元素的组合,然后希望尽可能地接近300个元素

height=[67, 67, 55, 65, 65, 65, 61, 58, 40, 40, 58, 53, 59, 63, 51, 57, 43, 65, 45, 65, 61, 58, 47, 58, 65, 74, 64, 28, 61, 46, 39]

valid_combs = []

import itertools
for comb in itertools.combinations(height, 6):
    #if sum(comb) <= 300 and sum(comb) >+ 290:
    if sum(comb) == 300:
        valid_combs.append(comb)
        print(comb)

这将从集合中提取有效的6种长度组合,然后检查其总和是否为300。上面的注释条件是您是否希望将其包含在290至300等范围内

您可以根据需要修改条件,例如if sum(comb) >= 250

答案 4 :(得分:0)

最初我可能误解了这个问题。但是,重新考虑输入后,您的目标是对数据进行分组,以使未指定长度的总和不超过某个阈值。使用numpy可能是一个不错的起点:

edit:这假定需要保留数据的顺序,否则我将使用基于分位数的方法。 edit2:不保存订单

    import numpy as np
height = np.array(\
                  [67, 67, 55, 65, 65, 65, 61, 58, 40, 40,\
                   58, 53, 59, 63, 51, 57, 43, 65, 45, 65,\
                   61, 58, 47, 58, 65, 74, 64, 28, 61, 46, 39])
height.sort()
threshold = 300
groupings = np.where(np.diff(height.cumsum() // threshold))[0]
ends      = np.hstack((groupings, height.size))
starts    = np.roll(ends.copy(), 1) + 1
starts[0] = 0

for start, end in zip(starts, ends):
    print(f'Grouping: {height[start:end]} sum: {height[start:end].sum()}')

输出:

Grouping: [28 39 40 40 43 45] sum: 235
Grouping: [47 51 53 55] sum: 206
Grouping: [58 58 58 58 59] sum: 291
Grouping: [61 61 63] sum: 185
Grouping: [65 65 65 65] sum: 260
Grouping: [65 67 67 74] sum: 273

答案 5 :(得分:0)

我的方法是找到并使用组合来完全填充300个总高度的单元格。这不是最佳选择。

    import itertools

    height=[67, 67, 55, 65, 65, 65, 61, 58, 40, 40, 58, 53, 59, 63, 51, 57, 43, 65, 45, 65, 61, 58, 47, 58, 65, 74, 64, 28, 61, 46, 39]

def fill_cell(cells, comb):
    cells.append(comb) #fill cell
    for h in comb:
        del height[height.index(h)] #delete elemets from heights array

cells = []

找到第一个必需的组合时-我fill_cell并从height数组中删除使用过的元素。
由于每个单元格中没有物品数量限制-我将更改此数目。
在这种情况下,总共有7个项目的总高度为300:

for comb in itertools.combinations(height, 7):
    if sum(comb) == 300:
        print(comb) #(55, 40, 40, 53, 45, 28, 39)
        fill_cell(cells,comb)
        print(len(height)) #24
        break

此后,我发现了5种物品的组合,总高度为300。

for comb in itertools.combinations(height, 5):
    if sum(comb) == 300:
        print(comb) #(67, 67, 65, 58, 43)
        fill_cell(cells,comb)
        print(len(height)) #19
        break

for comb in itertools.combinations(height, 5):
    if sum(comb) == 300:
        print(comb)
        fill_cell(cells,comb) #(65, 65, 61, 58, 51)
        print(len(height)) #14
        break

for comb in itertools.combinations(height, 5):
    if sum(comb) == 300:
        print(comb)
        fill_cell(cells,comb) #(59, 63, 57, 47, 74)
        print(len(height)) # 9
        break

这时我有4个单元格,它们的总高度直接为300。
我没有找到更多直接具有300总高度的组合。 我决定手动定义剩余的单元格:

print(cells)
print(height)

fill_cell(cells,height[:4])
fill_cell(cells,height[:])

print("Result:")
for c in cells:
    print(sum(c), c)

print("Total height: ", sum([sum(c) for c in cells]))

最后:

Result:
300 (55, 40, 40, 53, 45, 28, 39)
300 (67, 67, 65, 58, 43)
300 (65, 65, 61, 58, 51)
300 (59, 63, 57, 47, 74)
249 [65, 65, 61, 58]
294 [58, 65, 64, 61, 46]
Total height:  1743

更新: 以下代码执行相同的操作。如果找不到300个高度的组合,则会迭代更改组合参数并降低高度限制:

import itertools

height=[67, 67, 55, 65, 65, 65, 61, 58, 40, 40, 58, 53, 59, 63, 51, 57, 43, 65, 45, 65, 61, 58, 47, 58, 65, 74, 64, 28, 61, 46, 39]

def fill_cell(cells, comb):
    cells.append(comb) #fill cell
    for h in comb:
        del height[height.index(h)] #delete elemets from heights array

cells = []
max_height = 300
max_elements = 7
elements = max_elements
cell_filled = True


while height:
    if cell_filled == False:
        elements-=1
    if elements==0:
        elements = max_elements
        max_height-=1

    for comb in itertools.combinations(height, min(elements,len(height))):
        if sum(comb) == max_height:
            print(comb)
            fill_cell(cells, comb)
            print(len(height))
            cell_filled = True
            break
        cell_filled = False


print("Result:")
for c in cells:
    print(sum(c), c)

print("Total height: ", sum([sum(c) for c in cells]))