如何使用 Python 并遵循一组最小和最大要求将数值分成 N 个不均匀的部分?

How to divide a number value in N unevenly parts using Python & following a set of min- & max requirement?

我在 Python 中有一个相当基础的数学问题,但我不知道去哪里找。

解释:

我唯一的要求如下:


from random import randint, shuffle

def divide_number(number, parts_number, allow_zero = False ):

    if (parts_number > number):
        raise ValueError("Number of parts can't be higher than the number");

    parts = {currency: []}
    number_rest = number

    for i in range(1, parts_number + 1):
        if (i == parts_number):
            parts[currency].append(number_rest)
            break
        else:
            new_number = randint(0, number_rest) if allow_zero else randint(1, (number_rest - 
(parts_number - i)) // 2)

        number_rest -= new_number
        parts[currency].append(new_number)

    return parts

运行函数:

divide_number(100, 10)

输出

[2, 37, 8, 10, 2, 4, 4, 4, 26, 3]

我在网上找到的这段代码似乎工作得很好,但它不符合我的要求。我该如何改变它才能满足我对 minmax 值的要求?

基本上,我想从不公平分配转变为公平分配

每次下一次迭代,您必须确保您有足够的剩余资金来至少向所有朋友提供最低金额:

from random import randrange

def divide_number(number, divider, min_value, max_value):
    result = []
    for i in range(divider - 1, -1, -1):
        part = randrange(min_value, min(max_value, number - i * min_value + 1))
        result.append(part)
        number -= part
    return result

用法:

divide_number(100, 10, 5, 40)

注意,先参与的朋友更有机会获得更多。您可以通过在函数 return:

之前添加 shuffle() 使其更“公平”
from random import shuffle

def divide_number(...):
    ...
    shuffle(result)
    return result

在有限制的情况下进行相当公平的分配并不容易。 对于合理的总和和部分 (p) 值,我们可以制作 p 个单元格(朋友口袋)并随机将硬币逐个硬币放入其中(如果可能)

import random

def randparts(summ, p, minn, maxx):
    maxx = maxx - minn
    summ -= p * minn
    if summ < 0:
        return None
    if p * maxx  >=  summ * 2:
        lst = [0] * p
        while summ > 0:
            r = random.randrange(p)
            if lst[r] < maxx:
                summ -= 1
                lst[r] += 1
    else:
        lst = [maxx] * p
        summ = maxx * p - summ
        while summ > 0:
            r = random.randrange(p)
            if lst[r] > 0:
                summ -= 1
                lst[r] -= 1
    for i in range(len(lst)):
        lst[i] += minn
    return lst

print(randparts(100, 10, 5, 40))

>>>[7, 17, 8, 10, 8, 8, 9, 12, 10, 11]

来自 Olvin Roght 评论的更简洁和 pythonic 版本(还删除了第二个分支以优化大 summ 值)

def randparts(number, divider, min_value, max_value):
    sum_min = divider * min_value
    if sum_min > number:
        return

    number -= sum_min
    result = [min_value] * divider
    while number:
        pocket = randrange(divider)
        if result[pocket] <= max_value:
            result[pocket] += 1
            number -= 1

    return result