假设我有一条 n 长的行,并且我有一个或多个具有指定尺寸的线段类型(让我们称之为项目)。使用那些"项目"我需要在尝试维持段之间的指定比率时填充线。必须尽可能地填充线,即使这意味着比率不完全匹配。该生产线不能过满。
SAMPLE INPUT
available_length = 15
A:尺寸= 2,理想比率= 1/3
B:大小= 4,理想比率= 2/3
SAMPLE OUTPUT
3 A(2 * 3 = 6)
B中的2个(4 * 2 = 8)余数= 1(15-14 = 1)
以下是我到目前为止的代码,唯一的问题是我不确定这是否是一个很好的方法来做这个并且我不确定如何填写剩余部分
available_length = 15
item_set = {
'a': {'length': 2.0, 'fraction': 0.33},
'b': {'length': 4.0, 'fraction': 0.66},
}
results = {}
for item, item_data in item_set.iteritems():
results[item] = {}
ideal_total_length = available_length * item_data['fraction']
rounded_ideal_total_length = round(ideal_total_length / item_data['length']) * item_data['length']
possible_multiples = rounded_ideal_total_length / item_data['length']
results[item].update({
'length': item_data['length'],
'fraction': item_data['fraction'],
'multiples': possible_multiples,
})
used_length = sum([results[i]['length'] * results[i]['multiples'] for i in results])
remainder = available_length - used_length
print results
print "remainder: ", remainder
答案 0 :(得分:0)
您只需更新item_set并执行此操作
available_length = 15
item_set = {
'a': {'length': 2.0, 'fraction': 0.33},
'b': {'length': 4.0, 'fraction': 0.66},
}
small = available_length
rem = available_length
while rem > 0:
for k, v in item_set.items():
small = min(v['length'], small)
if 'cnt' in v:
if v['length'] < rem:
v['cnt'] += 1
else:
v['cnt'] = int(available_length * v['fraction'] / v['length'])
rem = available_length - sum(v['length'] * v['cnt'] for v in tem_set.values())
if rem == 0 or rem < small:
break
print rem
print item_set
3,1 Top
答案 1 :(得分:0)
这是我找到的解决方案。我应该注意到,对于整体非常小且开始和结束之间的距离非常大的问题,它不会很好用,但它对我的目的很有用。
from operator import itemgetter
import itertools
def fill_remaining(fill_data_dict, n_from, n_to):
combo_depth = 5 # this is the limit for number of moves
if n_from > n_to:
# if we need to be able to move backwards
source_dict = {}
for key, fill_value in fill_data_dict.iteritems():
pos_key = '[+]' + key
source_dict[pos_key] = fill_value
neg_key = '[-]' + key
neg_data = fill_value * -1
source_dict[neg_key] = neg_data
source_dict[None] = None
move_combo_set = list(itertools.combinations_with_replacement(source_dict, combo_depth))
else:
source_dict = {}
for key, fill_value in fill_data_dict.iteritems():
pos_key = '[+]' + key
source_dict[pos_key] = fill_value
source_dict[None] = None
move_combo_set = list(itertools.combinations_with_replacement(source_dict, combo_depth))
# use combo list to find best combinaton
results = []
for row_index in xrange(len(move_combo_set)):
n_sum = n_from
for i in move_combo_set[row_index]:
if i:
n_sum += source_dict[i]
# diff = result from combo - target number ... so a positive number means we went over
diff = n_sum - n_to
moves_number = len(filter(None, move_combo_set[row_index]))
if diff <= 0:
results.append([row_index, diff, moves_number])
# sort to get best result
rs_2 = sorted(results, key=itemgetter(2)) # sort by moves (secondary)
rs_1 = sorted(rs_2, key=itemgetter(1), reverse=True) # then by diff (the primary)
if rs_1:
best_result_index = rs_1[0][0]
best_result = filter(None, move_combo_set[best_result_index])
return best_result
else:
return ()
fill_data_dict = {
'A': 1,
'B': 3,
}
n_from = 18
n_to = 24
fill = fill_remaining(fill_data_dict, n_from, n_to)
print fill