如何使用 Python 并遵循一组最小和最大要求将数值分成 N 个不均匀的部分?
How to divide a number value in N unevenly parts using Python & following a set of min- & max requirement?
我在 Python 中有一个相当基础的数学问题,但我不知道去哪里找。
解释:
- 我有 100 美元。
- 我有 10 个朋友。
- 我想不均匀地把我的钱分给朋友。
- 我想用算法一遍又一遍地做这个。
我唯一的要求如下:
- 任何朋友可以收到的最小金额应 > 5 美元。
- 任何朋友可以收到的最大金额应小于 $40。
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]
我在网上找到的这段代码似乎工作得很好,但它不符合我的要求。我该如何改变它才能满足我对 min 和 max 值的要求?
基本上,我想从不公平分配转变为公平分配。
每次下一次迭代,您必须确保您有足够的剩余资金来至少向所有朋友提供最低金额:
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
我在 Python 中有一个相当基础的数学问题,但我不知道去哪里找。
解释:
- 我有 100 美元。
- 我有 10 个朋友。
- 我想不均匀地把我的钱分给朋友。
- 我想用算法一遍又一遍地做这个。
我唯一的要求如下:
- 任何朋友可以收到的最小金额应 > 5 美元。
- 任何朋友可以收到的最大金额应小于 $40。
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]
我在网上找到的这段代码似乎工作得很好,但它不符合我的要求。我该如何改变它才能满足我对 min 和 max 值的要求?
基本上,我想从不公平分配转变为公平分配。
每次下一次迭代,您必须确保您有足够的剩余资金来至少向所有朋友提供最低金额:
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