2015-12-08 2 views
1

Мне нужно разделить заданное количество предметов (скажем, 10) с использованием заданного отношения [0.55, 0.45]. Результат здесь должен быть 6: 4 или 5: 5. Обычный подход [0.55*10, 0.45*10] приведет к [6, 5] (11, а не 10).Подразделение целых чисел с использованием заданного отношения без создания поплавок

Другой пример: разделитель 7 с использованием коэффициента: [0.36, 0.44, 0.07, 0.07, 0.03, 0.03] который идеально должен давать что-то вроде [3, 3, 1, 0, 0, 0] или [3, 3, 0, 1, 0, 0].

Что было бы хорошим подходом к этой проблеме?

+0

Вы пытались решить эту проблему? Если у вас есть, отредактируйте свой вопрос, чтобы включить свой код и исследование, чтобы показать, что не сработало для вас. Если вы этого не сделали, сначала попытайтесь решить эту проблему, а затем опубликуйте код и исследуйте здесь. Это затрудняет ответ другим пользователям! – SuperBiasedMan

+0

См. Этот [stackoverflow] (http://stackoverflow.com/questions/2356501/how-do-you-round-up-a-number-in-python) и этот [python math] (https: // docs. python.org/2/library/math.html) –

+0

Я мог бы написать что-то, что после этого, как в первом примере, в конечном итоге с [6,5] будет измеряться, если в нем больше или меньше, а затем просто, если больше, удалите один из самого большого числа или, если меньше, добавьте в самый высокий коэффициент, который еще ничего не имеет. Однако мне было интересно, есть ли какой-то умный математический способ сделать это. – SecondLemon

ответ

1

Вот моя попытка по этому вопросу :) Самая сложная часть, которая реверсирует операцию сортировки и сопоставляет ее с результатами ... Если вам не нужно сохранять исходный порядок отношений, вы можете удалить часть последнего функция.

def scale_ratio(ratios: list) -> list: 
    sum_ = sum(ratios) 
    return [x/sum_ for x in ratios] 

def ratio_breakdown_recursive(x: int, ratios: list) -> list: 
    top_ratio = ratios[0] 
    part = round(x*top_ratio) 
    if x <= part: 
     return [x] 
    x -= part 
    return [part] + ratio_breakdown_recursive(x, scale_ratio(ratios[1:])) 


def ratio_breakdown(x: int, ratios: list) -> list: 
    sorted_ratio = sorted(ratios, reverse=True) 
    assert(round(sum(ratios)) == 1) 
    sorted_result = ratio_breakdown_recursive(x, sorted_ratio) 
    assert(sum(sorted_result) == x) 
    # Now, we have to reverse the sorting and add missing zeros 
    sorted_result += [0]*(len(ratios)-len(sorted_result)) 
    numbered_ratios = [(r, i) for i, r in enumerate(ratios)] 
    sorted_numbered_ratios = sorted(numbered_ratios, reverse=True) 
    combined = zip(sorted_numbered_ratios, sorted_result) 
    combined_unsorted = sorted(combined, key=lambda x: x[0][1]) 
    unsorted_results = [x[1] for x in combined_unsorted] 
    return unsorted_results 

Результаты:

ratio_breakdown(7, [0.36, 0.44, 0.07, 0.07, 0.03, 0.03]) 
[3, 3, 1, 0, 0, 0] 
ratio_breakdown(10, [0.55, 0.45]) 
[6, 4] 
ratio_breakdown(16, [0.16, 0.47, 0.13, 0.24]) 
[2, 8, 2, 4] 

EDIT: Это Python3.

+0

Спасибо, выглядит многообещающе.Позвольте мне изучить его на некоторое время, и я сообщаю вам. (не имеет значения, находится ли он в 3 или 2,7) – SecondLemon

+0

Мне немного сложно понять, что происходит иногда, но я получаю его суть. Однако, что здесь происходит (еще один пример): 'ratio_breakdown (16, [0,16, 0,47, 0,13, 0,24]) -> [2, 3, 3, 8]' – SecondLemon

+0

Очевидно, что-то не так: D Позвольте мне посмотреть, если я может исправить это. – Maciek

2

Я предлагаю вам иметь еще один массив. Я новичок в Python.

Вот код с вашим примером (вы можете просто адаптировать его, я уверен):

a = [0.36, 0.44, 0.07, 0.07, 0.03, 0.03] 

numberItem = 7 
remainder = numberItem 


b = [0,0,0,0,0,0] 

for i in range(0,6): 
    b[i] = round(a[i]*numberItem) 
    if (b[i] > remainder) or (b[i] == 0): 
     b[i] = remainder 
     remainder = 0 
    else: 
      remainder = remainder - b[i] 
    print(b[i]) 

С этой границей, вы не можете иметь больше элементов, чем указано. Лучше, если массив отношений отсортирован от большего к меньшему.

+0

Вау ... Также очень приятно. Почти стыдно я уже отдал ответ. Позвольте мне немного проверить это. – SecondLemon

+0

Это тоже очень приятно и хорошо. Однако ответ Масика кажется немного более острым. Если вы посмотрите на этот пример: 16 образцов с отношением [0,47, 0,24, 0,16, 0,13], ваш алгоритм возвращает [8,4,3,1] и Maciek [8,4,2,2]. Хороший подход, хотя! – SecondLemon

+0

Я видел алгоритм Maciek после, и он кажется более полным :-) – Iggy

Смежные вопросы