const sum = array => array.reduce((accumulator, value) => (accumulator += value), 0);
const breakUp = (number, count) => {
const minimal = (count * (count + 1)) / 2;
if (minimal > number) {
throw new Error(`Число ${number} слишком маленькое. Минимальное допустимое число ${minimal}.`);
}
const numbers = Array.from({ length: count }, (_, index) => (count - index));
numbers.forEach((value, index, array) => {
const total = sum(array);
const remainder = number - total;
if (total < number) {
const random = (index === count - 1)
? remainder + value
: Math.floor(Math.random() * remainder);
array[index] = random;
}
});
const isUnique = new Set(numbers).size === numbers.length;
if (!isUnique) {
return breakUp(number, count);
} else {
return numbers.sort((a, b) => (b - a));
}
};
const breakUp = (number, count) => {
const numbers = [];
for (let index = 0; index < count; index++) {
const random = index === count - 1
? number
: Math.round(Math.random() * number);
numbers.push(random);
number -= random;
}
numbers.sort((a, b) => b - a);
return numbers;
};
const numbers = breakUp(100, 4);
console.log(numbers); // [76, 15, 6, 3]
const breakUp = (number, count) => Array.from({ length: count }, (_, index) => {
const random = index === count - 1
? number
: Math.round(Math.random() * number);
number -= random;
return random;
}).sort((a, b) => b - a);
const breakUp = (number, count) => {
const numbers = new Set();
while (numbers.size < count) {
const previousSize = numbers.size;
const random = numbers.size === count - 1
? number
: Math.floor(Math.random() * number);
numbers.add(random);
if (previousSize < numbers.size) {
number -= random;
}
}
return [...numbers.values()].sort((a, b) => b - a);
};
1. (x+y+z+m+r<100)?(x+=r):break
2. (y+r<x&&x+y+z+m+r<=100)?y+=r:goto 1
3. (z+r<y&&x+y+z+m+r<=100)?z+=r:goto 1
4. (m+r<z&&x+y+z+m+r<=100)?m+=r:goto 1
5. goto 1
x > y
, значит, x = y + ненулевое_число
. Можно так перезаписать слагаемые:m = k0
z = m + k1 = k0 + k1
y = z + k2 = k0 + k1 + k2
x = y + k3 = k0 + k1 + k2 + k3
-----------------------------
m+z+y+x = 4k0 + 3k1 + 2k2 + k3 = SUM
ki — это натуральные числа от 1. k
— вычислили x, y, z, m.k0
k1..k3
уходит минимум 6, когда все по 1,k0
остаётся диапазон [1, (SUM - 6) / 4]
k0
должен быть целым.k0
в этом диапазоне, SUM1 = SUM - 4 * k0
,3k1 + 2k2 + k3 = SUM1
k3
это весь остаток.const addUpTo = (top, n) => {
const getDiffs = (sum, n, acc = []) => {
if (n === 1) {
x = sum;
} else {
const headroom = (n - 1) * n / 2;
const cap = Math.floor((sum - headroom) / n);
if (cap < 1) throw("Impossible. " + JSON.stringify(acc));
x = 1 + Math.floor(Math.random() * cap);
}
acc.push(x);
if (n <= 1) {
return acc;
} else {
return getDiffs(sum - x * n, n - 1, acc);
}
}
return getDiffs(top, n).map((_, i, a) => a.reduce((acc, c, j) => j <= i ? acc + c : acc)).reverse();
}
addUpTo(100, 4) /*
[ 34, 30, 21, 15 ]
[ 31, 24, 23, 22 ]
[ 66, 17, 13, 4 ]
[ 47, 22, 21, 10 ]
...
*/
addUpTo(10, 4) // [ 4, 3, 2, 1 ]
addUpTo(9, 4) // ошибка, невозможно разложить