Задать вопрос
TonyStark1337
@TonyStark1337

Случайные числа с заданной сумой, какой алгоритм?

Привет, какой алгоритм уже есть или как сделать свой если надо найти 4 рандомных числа сума которых ровна N, допустим x+y+z+m = 100, где каждая больше другой, то есть x > y > z > m. У кого какие мысли ?
  • Вопрос задан
  • 317 просмотров
Подписаться 2 Средний 2 комментария
Решение пользователя Александр К ответам на вопрос (6)
Seasle
@Seasle Куратор тега JavaScript
Вариант 4 - Окончательный.
Возвращает массив уникальных чисел больше нуля отсортированных по убыванию. Имеется проверка на возможность разделения числа на более мелкие.
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));
  }
};


Другие варианты

Вариант 1.
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]


Вариант 2.
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);


Вариант 3.
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);
};

Ответ написан