Algorithm 如何将一个数字分成多个部分(不相等),使之和等于输入?

Algorithm 如何将一个数字分成多个部分(不相等),使之和等于输入?,algorithm,Algorithm,我想将一个数字(例如输入数字,即40)分成不同的令牌(30个部分),从一个范围中随机选择,其总和必须等于输入数字,即40。 编辑: 最大范围应为40%,最小范围应为0 示例: range = (0,4) 1+1+0+1+1+0+3+0+3+0+0+2+0+4+4+1+1+0+1+1+0+3+0+4+0+2+2+0+4+1 = 40. 实际上,在现实世界中显示场景的结果,我有一个产品用户表达式的总和,我需要随机填充到上个月每天的记录集中。我正在使用php,但无法获得处理这种情况的算法。因为您提

我想将一个数字(例如输入数字,即40)分成不同的令牌(30个部分),从一个范围中随机选择,其总和必须等于输入数字,即40。 编辑: 最大范围应为40%,最小范围应为0

示例:

range = (0,4)

1+1+0+1+1+0+3+0+3+0+0+2+0+4+4+1+1+0+1+1+0+3+0+4+0+2+2+0+4+1 = 40.

实际上,在现实世界中显示场景的结果,我有一个产品用户表达式的总和,我需要随机填充到上个月每天的记录集中。我正在使用php,但无法获得处理这种情况的算法。

因为您提到它是针对“上个月每天的记录集”,我假设令牌的数量也可能是28或31,因为您说的是“随机”,所以我会这样做:

1. create a function that takes in:
    a. The number to sum to (40 in your example).
    b. The maximum number of a single token (4 in your example).
    c. The number of tokens (30 in your example).
2. Within the function, create an array the size of the number of tokens (28, 30, 31, or whatever)
3. Initialize all elements of the array to zero.
4. Check to make sure that it is possible to achieve the sum given the maximum single token value and number of tokens.
5. While I need to increment a token (sum > 0):
    a. Select a random token.
    b. Determine if the value of the token can be incremented without going over the max single token value.
    c. If it can, then increment the token value and decrement the sum.
    d. If the token cannot be incremented, then go back to 5a.
6. Return the array of tokens, or however you want them back (you didn't specify).
下面是c#中的一个示例:

public int[]SegmentSum(int-sum,int-maxPart,int-parts)
{
如果(总和<0 | |最大部分<0 | |部分<0 | |部分*最大部分<总和)
抛出新ArgumentOutOfRangeException;
随机rnd=新随机();
int[]tokens=可枚举。重复(0,部分).ToArray();
而(总和>0)
{
int token=rnd.Next(部分);
if(令牌[令牌]
希望这对您有所帮助。

简单方法利用“试错”方法。适用于合理的小输入值

注意-当
n
接近
p*maxx
时,它可能会工作很长时间。如果这种情况是可能的,那么更明智的做法是分配“洞”而不是“一个”(第二个代码)

随机导入
def随机部件(n、p、maxx):
lst=[0]*p
当n>0时:
r=随机。随机范围(p)
如果lst[r]>>  [2, 0, 3, 2, 4, 2, 1, 3, 0, 3]

def-randparts(n、p、maxx):
如果p*maxx>=n*2:
lst=[0]*p
当n>0时:
r=随机。随机范围(p)
如果lst[r]0时:
r=随机。随机范围(p)
如果lst[r]>0:
n-=1
lst[r]-=1
返回lst
印刷品(第16、10、4部分)
印刷品(第32、10、4部分)
>> [2, 0, 0, 3, 4, 0, 0, 3, 2, 2]
>> [3, 4, 4, 4, 4, 0, 3, 3, 4, 3]

请添加算法常数的附加信息,例如,范围是否在限制范围内?输入数是否总是大于令牌数?定义您的问题以便我们可以帮助您您尝试了什么?发布你的代码!
public int[] SegmentSum(int sum, int maxPart, int parts)
{
    if (sum < 0 || maxPart < 0 || parts < 0 || parts * maxPart < sum)
        throw new ArgumentOutOfRangeException;

    Random rnd = new Random();
    int[] tokens = Enumerable.Repeat(0, parts).ToArray();

    while(sum > 0)
    {
        int token = rnd.Next(parts);
        if (tokens[token] < maxPart)
        {
            tokens[token]++;
            sum--;
        }
    }
    return tokens;
}
import random

def randparts(n, p, maxx):
    lst = [0] * p
    while n > 0:
        r = random.randrange(p)
        if lst[r] < maxx:
            n -= 1
            lst[r] += 1
    return lst

print(randparts(20, 10, 4))

>>>  [2, 0, 3, 2, 4, 2, 1, 3, 0, 3]
def randparts(n, p, maxx):
    if p * maxx  >=  n * 2:
        lst = [0] * p
        while n > 0:
            r = random.randrange(p)
            if lst[r] < maxx:
                n -= 1
                lst[r] += 1
    else:
        lst = [maxx] * p
        n = maxx * p - n
        while n > 0:
            r = random.randrange(p)
            if lst[r] > 0:
                n -= 1
                lst[r] -= 1
    return lst

print(randparts(16, 10, 4))
print(randparts(32, 10, 4))

>> [2, 0, 0, 3, 4, 0, 0, 3, 2, 2]
>> [3, 4, 4, 4, 4, 0, 3, 3, 4, 3]