Получить массив чисел, сумма которого не больше n

108
29 декабря 2020, 09:50

Итак, привет.

Недавно задумался над функцией которая бы или разбивала число на несколько рандомных слагаемых (К примеру 5), сумма которых бы не превышала первично заданное число (n).

Или генерировала массив с несколькими числами (К примеру 5-ю), сумма которых бы не превышала первично заданное число (n). Т.е. массив из 5-ти чисел, сумма которых не должна превышать 10.

Решил пойти по второму пути, так как по первому вообще ничего не приходило в голову, и вот создал скрипт который бы генерировал массив, но тут загвоздка.

А именно: Как ограничить сумму чисел(Элементов) массива до числа n (К примеру 10), чтобы при этом элементов в массиве было минимум 5 штук,и не более 5-ти.

Загвоздка в том, что не понимаю как вообще выполняется первая функция что я описал.

Мне бы объяснение и пример любой рабочей функции, хоть первой, хоть второй. А то хоть убей не могу понять как происходит сие действо, прошу вашей помощи

Код прилагаю:

let n = 10, 
    numbers = [], 
    sum = 0; 
 
    function randomNum(min, max) { 
        let rand = min - 0.5 + Math.random() * (max - min +1); 
        rand = Math.round(rand); 
        writeArr(rand); 
    } 
    function writeArr(rand) { 
        numbersLength = numbers.length; 
        numbers[numbersLength] = rand; 
        countArr(); 
        // console.log(numbersLength); 
        // console.log(numbers) 
        // console.log(countWork) 
    } 
    function countArr() { 
      sum = 0; 
        for (let i = 0; i < numbers.length; i++) { 
            sum += numbers[i]; 
        } 
        // if (sum > 11) { 
        //   numbers = []; 
        //   // for (let i = 0; i < 5; i++) randomNum(1, n); 
        //   if (numbersLength < 5) { 
        //     // return 
        //   } 
        // } 
        console.log(numbers) 
        console.log(sum) 
        if (numbers.length >= 5) { 
            clearArr(); 
        } 
    } 
    function clearArr() { 
      sum = 0; 
      numbers = []; 
    } 
// for (let i = 0; i < 5; i++) randomNum(1, n); 
 
function startScript() { 
  for (let i = 0; i < 5; i++) randomNum(1, n); 
} 
 
const start = document.querySelector('.Start'); 
 
start.addEventListener('click', startScript)
<!DOCTYPE html> 
<html lang="en"> 
<head> 
	<meta charset="UTF-8"> 
	<title>Document</title> 
</head> 
<body> 
	<button class="Start">Start</button>			 
	<script async src="partition.js"></script> 
</body>  
</html>

Answer 1

const input = document.getElementById('input'); 
const output = document.getElementById('output'); 
 
const getRandomInt = (min, max) => 
  Math.floor(Math.random() * (max - min + 1)) + min; 
   
 
const getNumComponents = num => { 
  const components = []; 
  let currentSum = 0; 
   
  for(let i = 4; i >= 0; i--) { 
    const component = getRandomInt(1, num - currentSum - i); 
    components.push(component); 
    currentSum += component; 
  } 
   
  return components; 
}; 
 
input.onchange = e => { 
  const {value} = e.target; 
  if(!value) { 
    return; 
  } 
 
  const num = parseInt(value, 10); 
  if(isNaN(num)) { 
    return alert('Не число'); 
  } 
   
  if (num < 5) { 
    return alert('Число слишком маленькое'); 
  } 
   
  const result = getNumComponents(num); 
  console.info(result, result.reduce((a, r) => r += a, 0)); 
};
<input id='input' placeholder='Введите число'><br> 
<div id='output'></div>

Алгоритм такой: На каждом шагу мы берем число, вычитаем из него уже имеющуюся сумму + номер шага. Зачем нужно вычитать номер шага? Это гарантирует, что для каждого минимальное возможное число равно 1, так мы избавляем то нулей.
Например: num = 10

1 шаг - Случайное число будет между [1 и 6] ( 10 - 0 - 4 ) (выпало) => 1
2 шаг - Случайное число будет между [1 и 6] ( 10 - 1 - 3 ) => 5
3 шаг - Случайное число будет между [1 и 2] ( 10 - 6 - 2 ) => 1
4 шаг - Случайное число будет между [1 и 2] ( 10 - 7 - 1 ) => 2
5 шаг - Случайное число будет между [1 и 1] ( 10 - 9 - 0 ) => 1

Это гарантирует что в сумме не будет нулей

При маленьких числах часто будет 0 попадаться, если хотите его убрать, то тогда с низу будет ограничение числа равное 5 ( попробуйте сами реализовать )

READ ALSO
Как сделать половину слайда?

Как сделать половину слайда?

подскажите пожалуйста каким образом можно сделать показ половину слайда? Использую slick, но можно дать советы и по другим слайдерамСпасибо

98
Rand() возвращает только половину из возможных значений, как бороться?

Rand() возвращает только половину из возможных значений, как бороться?

Функция rand() возвращает псевдослучайное число от 0 до 2^31 -1Она никогда не возвращает отрицательные числа, но при этом "ворует" аж половину диапазона...

107