I'm trying to come up with a solution where I need to roll a number of dice (all of the same size) and come to a specified number. Provided I have all the validation in place to make sure the numbers are valid and could theoretically arrive at the desired result, does anyone have a good algorithm for solving this? Note it should appear random, not just a straight divide.
Some examples
roll 3 d6 and get 14 -> so it could output 5,3,6 or 6,6,2
roll 4 d20 and get 66 -> so it could output 16,14,19,17
I need a generic function that can accept a dice of any size, any amount to be rolled and the desired result.
My initial attempt is below, though this doesn't produce the desired output (you can ignore the mod for now, this was to also allow modifiers). This example is also missing the validation that the desired output is achievable,but that's not part of the question.
let desired = 19
let mod = 0
let dm = desired - mod
let n = 5;// number of dice
let d = 6 // dice sides
let nums = []
for(i =0; i< n; i++) {
nums.push(Math.round(Math.random() * Math.round(d)) + 1)
}
let sum = nums.reduce((acc,val) => acc + val)
nums = nums.map(a => Math.round((a/sum) * dm))
let diff = dm - (nums.reduce((acc,val) => acc + val))
function recursive(diff) {
let ran = nums[Math.random() * Math.round(nums.length -1)]
if(nums[ran] + diff > d || nums[ran] + diff < 1) {
recursive(diff)
} else {
nums[ran] += diff
}
}
while(diff != 0) {
recursive(diff)
diff += diff < 0 ? 1 : -1;
}
alert(nums)
recursive:
function foo(desired, rolls, sides, current) {
if (rolls === 0) {
return current.reduce((s, c) => s + c) === desired ? current : null;
}
const random = [];
for (let i = 1; i <= sides; i++) {
const randomIndex = Math.floor(Math.random() * (random.length + 1))
random.splice(randomIndex, 0, i);
}
for (const n of random) {
const result = foo(desired, rolls - 1, sides, [...current, n]);
if (result) {
return result;
}
}
}
console.log(foo(14, 3, 6, []))
non-recursive:
function foo(desired, rolls, sides) {
const stack = [[]];
while (stack.length) {
const current = stack.pop();
const random = [];
for (let i = 1; i <= sides; i++) {
const randomIndex = Math.floor(Math.random() * (random.length + 1));
random.splice(randomIndex, 0, i);
}
for (const n of random) {
if (current.length === rolls - 1) {
if (current.reduce((s, c) => s + c + n) === desired) {
return [...current, n];
}
} else {
stack.push([...current, n]);
}
}
}
}
console.log(foo(14, 3, 6));
non-recursive with minimum memory consumption:
function foo(desired, rolls, sides) {
const currentIndexes = Array(rolls).fill(0);
const randoms = Array.from({ length: rolls }, () => {
const random = [];
for (let i = 1; i <= sides; i++) {
const randomIndex = Math.floor(Math.random() * (random.length + 1));
random.splice(randomIndex, 0, i);
}
return random;
})
while (true) {
if (currentIndexes.reduce((s, idx, i) => s + randoms[i][idx], 0) === desired) {
return currentIndexes.map((idx, i) => randoms[i][idx]);
}
for (let i = currentIndexes.length - 1; i >= 0; i--) {
if (currentIndexes[i] < sides - 1) {
currentIndexes[i] += 1;
break;
}
currentIndexes[i] = 0;
}
}
}
console.log(foo(14, 3, 6));
non-recursive solution with minimum memory consumption and increased performance by calculating the last roll based on previous rolls.
function foo(desired, rolls, sides) {
const currentIndexes = Array(rolls - 1).fill(0);
const randoms = Array.from({ length: rolls - 1 }, () => {
const random = [];
for (let i = 1; i <= sides; i++) {
const randomIndex = Math.floor(Math.random() * (random.length + 1));
random.splice(randomIndex, 0, i);
}
return random;
})
while (true) {
const diff = desired - currentIndexes.reduce((s, idx, i) => s + randoms[i][idx], 0);
if (diff > 0 && diff <= sides) {
return [...currentIndexes.map((idx, i) => randoms[i][idx]), diff];
}
for (let i = currentIndexes.length - 1; i >= 0; i--) {
if (currentIndexes[i] < sides - 1) {
currentIndexes[i] += 1;
break;
}
currentIndexes[i] = 0;
}
}
}
console.log(foo(66, 4, 20));
Soluton in ruby:
def foo(count, dim, desired, results = [])
return results if count == 0
raise ArgumentError if count > desired
raise ArgumentError if count * dim < desired
max_roll = (dim <= desired - count) ? dim : desired - count + 1
min_roll = [(desired - (count-1) * dim), 1].max
roll = (rand(min_roll..max_roll))
results << roll
foo(count - 1, dim, desired - roll, results)
results
end
puts foo(3, 6, 11).inspect
puts foo(2, 6, 11).inspect
puts foo(4, 4, 11).inspect
Results:
[3, 4, 4]
[5, 6]
[2, 3, 4, 2]
So basically it is recursive function. For each step:
roll a dice (within allowed range min_roll..max_roll)
call same function but reduce count by already consumed number by dice and extend results array by value of roll
Note one thing: with this behaviour you may have larger numbers in the beginning of result. To avoid this just shuffle result of function in the end of it
Related
function isPerfectSquare(num)
{
let n = parseInt(Math.sqrt(num));
return (n * n == num);
}
// Function to check
// if the number is
// in Fibonacci or not
function checkFib(array, n)
{
let count = 0;
for (let i = 0; i < n; i++)
{
if (isPerfectSquare(5 * array[i] *
array[i] + 4) ||
isPerfectSquare(5 * array[i] *
array[i] - 4))
{
console.log(array[i] + " ");
count++;
}
}
if (count == 0)
console.log("None present + <br>");
}
// Driver Code
let array = [15, 1, ,3];
let n = array.length;
checkFib(array, n);
that is function to check nearest fibonaci how to get the output
Question : with Array [ 15, 1, 3 ] Expected Output is 2 because nearest fibonacci of 19 is 21 = 2
Thank u for help. :)
I just write code to get nearest fibonacci, may it should help you. It works !
const getNearestFibonacci = (array) => {
const total = array.reduce((acc, v) => acc + v);
let fibo = [0, 1];
do {
fibo = [...fibo, fibo[fibo.length - 1] + fibo[fibo.length - 2]];
} while (fibo[fibo.length - 1] < total);
const afterTotal = fibo[fibo.length - 1];
const beforeTotal = fibo[fibo.length - 2];
const next = afterTotal - total;
const prev = total - beforeTotal;
return next < prev ? next : prev;
};
console.log("getNearestFibonacci", getNearestFibonacci([15, 1, 3]));
Your code checks Fibonacci numbers in an array and outputs them. To check nearest Fibonacci, you need a number, why array? Are you summing numbers in array? If yes, then:
First, add array[i] as sum = sum + array[i]
Then, call NearestFibonacci (sum)
where,
NearestFibonacci (int sum){
if (sum == 0) {
cout << 0;
return;
}
int first = 0, mid = 1;
int last = first + mid;
while (last <= sum) {
first = mid;
mid=last;
last = first + mid;
}
int ans = min(last - sum, sum - mid);
cout << ans;
}
Input Arr=[1,2,3,4,5,6,7,8,9,10]
Expected output:-
Arr1 = [1,2,3,4,5,6,7] = 28
Arr2 = [8,9,10] = 27
The sum of arrays should be almost the same..
It can also be 3 or more parts
How to achieve this via custom function?
let Arr = [1,2,3,4,5,6,7,8,9,10]
const numberOfParts = 2
function SplitArr(Array, Parts){
/* ... */
}
let result = SplitArr(Arr,numberOfParts)
/* result should be [[1,2,3,4,5,6,7],[8,9,10]] */
/* output can be in any format as long as it can get the parts */
I think you can't do that directly by JS functions.
You have to create a custom function to achieve this.
I have considered dividing the array into 2 equal parts.
You can't always split the array equally. Here in this array, you can't partition array into more than 2 subparts, otherwise it will give more than 3 parts as some of the elements are present there having sum more than the partitioned Sum.
Note: I treated the array to be sorted, otherwise it depends on the usecase.
Note: I have updated the old implementation based on the updated question requirement
let arr=[1,2,3,4,5,6,7,8,9,10]
function splitArrayEqually(arr, parts=2){
//get the total sum of the array
let sum = arr.reduce((currentSum, value) => currentSum+value ,0);
//get the half sum of the array
let partitionedSum = Math.ceil(sum/parts);
let start=0, end=0, currentSum=0;
let splittedArray=[];
//get the index till which the sum is less then equal partitioned sum
while(end < arr.length){
if(currentSum+arr[end] > partitionedSum){
splittedArray.push(arr.slice(start,end));
start = end; //start new window from current index
currentSum = 0; //make sum =0
}
//add current end index to sum
currentSum += arr[end];
end++;
}
splittedArray.push(arr.slice(start));
return splittedArray;
}
splitted = splitArrayEqually(arr,3);
console.log(splitted)
let Arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const numberOfParts = 3
function sumOfArray(arr) {
if (arr) {
if (arr.length > 0) {
let sum = 0
for (let i = 0; i < arr.length; i++) sum += arr[i]
return sum
} else {
return 0
}
} else {
return 0
}
}
function SplitArr(Array, Parts) {
let lastIndex = 0
let result = []
function getReamingSum(arr) {
let psum = sumOfArray(Array.slice(lastIndex)) / Parts
console.log('psum ' + psum)
return psum + Parts
}
let psum = getReamingSum(Array)
for (let j = 0; j < Parts; j++) {
let total = 0
for (let i = 0; i < Array.length; i++) {
if (i >= lastIndex) {
total += Array[i]
if (total < psum || j === Parts - 1) {
if (result[j]?.length > 0) {
result[j].push(Array[i])
} else {
let arr = []
arr.push(Array[i])
result[j] = arr
}
lastIndex = i + 1
}
}
}
}
return result
}
let result = SplitArr(Arr, numberOfParts)
console.log(result)
Assuming the array isn't sorted,using a 2D array, with each sub array with sum almost equal to (sum of array / n).
let arr = [9,2,10,4,5,6,7,8,1,3]
arr.sort(function(a, b) { return a - b; });
const sum = arr.reduce((a, b) => a + b, 0);
const n = 2;
const result = [];
let s = 0;
let j = 0;
result[j] = [];
for(let i=0; i<arr.length; i++){
if(s <= Math.floor(sum/n)){
result[j].push(arr[i]);
s +=arr[i];
}
else{
s = 0;
j = j + 1;
result[j] = [];
result[j].push(arr[i]);
}
}
console.log(result)
O/P:
[ [1, 2, 3, 4,5, 6, 7], [ 8, 9, 10 ] ]
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const splitArray = (arr,parts) => {
const totalSum = arr.reduce((acc, item) => {
acc += item;
return acc;
}, 0)
const splitSum = Math.floor(totalSum / parts);
const arrObj = arr.reduce((acc, item,index) => {
acc.sum = acc.sum || 0;
acc.split = acc.split || {};
const pointer = Math.floor(acc.sum / splitSum);
//console.log(item,acc.sum, splitSum, pointer);
acc.split[pointer] = acc.split[pointer] || [];
acc.split[pointer].push(item);
acc.splitSum = splitSum;
acc.sum += item;
return acc;
}, {})
return arrObj;
}
console.log(splitArray(arr,2).split)
You're better off making a custom function:
let currentTotal = 0
let tempList = []
Arr.forEach(val => {
if (val >= 27) {
// push tempList to a new array
tempList = [];
currentTotal = val;
} else {
tempList.push(val);
currentTotal += val;
}
})
Question: Create a function that takes a positive integer and returns the next bigger number that can be formed by rearranging its digits. For example:
12 ==> 21
513 ==> 531
2017 ==> 2071
//nextBigger(num: 12) // returns 21
//nextBigger(num: 513) // returns 531
//nextBigger(num: 2017) // returns 2071
I am trying to compare two Array and get correct array as answer. In do...while loop I am comparing the two array by increment second array by one.
function nextBigger(n){
let nStrg = n.toString();
let nArr = nStrg.split('');
function compareArr(Ar1,Ar2){
if(Ar2.length>Ar1.length){
return false;
}
for(let i=0; i<Ar1.length; i++){
let num = Ar1[i];
for(let j=0; j<Ar2.length; j++){
if(Ar2.lastIndexOf(num) !== -1){
Ar2.splice(Ar2.lastIndexOf(num), 1);
break;
}
else{
return false;
break;
}
}
}
return true;
}
let nextNumArr;
let m = n;
do{
let nextNum = m+1
m=nextNum
let nextNumStrg = nextNum.toString();
nextNumArr = nextNumStrg.split('')
console.log(compareArr(nArr, nextNumArr))
}
while(compareArr(nArr, nextNumArr) == false)
console.log(nextNumArr)
return parseInt(nextNumArr.join())
}
nextBigger(12);
This gives me empty array at the end;
[2,0,1,7].join() will give you '2,0,1,7', can use [2,0,1,7].join('') and get '2017'
All looks a bit complicated. How about:
const nextLarger = num => {
const numX = `${num}`.split(``).map(Number).reverse();
for (let i = 0; i < numX.length; i += 1) {
if ( numX[i] > numX[i + 1] ) {
numX.splice(i, 2, ...[numX[i+1], numX[i]]);
return +(numX.reverse().join(``));
}
}
return num;
};
const test = [...Array(100)].map(v => {
const someNr = Math.floor(10 + Math.random() * 100000);
const next = nextLarger(someNr);
return `${someNr} => ${
next === someNr ? `not possible` : next}`;
}).join('\n');
document.querySelector(`pre`).textContent = test;
<pre></pre>
See also
function nextbig(number) {
let nums = []
number.toString().split('').forEach((num) => {
nums.push(parseInt(num))
})
number = nums
n = number.length
for (var i = n - 1; i >= 0; i--) {
if (number[i] > number[i - 1])
break;
}
if (i == 1 && number[i] <= number[i - 1]) {
return 'No greater possible'
}
let x = number[i - 1];
let smallest = i;
for (let j = i + 1; j < n; j++) {
if (number[j] > x &&
number[j] < number[smallest])
smallest = j;
}
let temp = number[smallest];
number[smallest] = number[i - 1];
number[i - 1] = temp;
x = 0
for (let j = 0; j < i; j++)
x = x * 10 + number[j];
number = number.slice(i, number.length + 1);
number.sort()
for (let j = 0; j < n - i; j++)
x = x * 10 + number[j];
return x
}
console.log(nextbig(12))
console.log(nextbig(513))
console.log(nextbig(2017))
In compareArr you are deleting elements as you find them, which is correct to do, to make sure duplicates actually occur twice etc. However, that also deletes the elements from nextNumArr in the calling context, because the array is passed by reference and not by value. You need to do a manual copy of it, for example like this: compareArr(nArr, [...nextNumArr]).
I have used a different approach, first I search for all possible combinations of the given numbers with the permutator function. This function returns an array of possible numbers.
Then I sort this array of combinations and look for the index of the given number in the main function.
Once I have this index I return the position before the given number.
function nextbig(num){
function permutator(inputArr){
let result = [];
const permute = (arr, m = []) => {
if (arr.length === 0) {
result.push(m)
} else {
for (let i = 0; i < arr.length; i++) {
let curr = arr.slice();
let next = curr.splice(i, 1);
permute(curr.slice(), m.concat(next))
}
}
}
permute(inputArr)
return result;
}
let arrNums = num.toString().split('')
let combinations = permutator(arrNums).map(elem => parseInt(elem.join("")))
combinations.sort((a, b) => {
return b - a
})
let indexOfNum = combinations.findIndex(elem => elem === num)
let nextBigIndex = indexOfNum <= 0 ? 0 : indexOfNum - 1
return (combinations[nextBigIndex])
}
console.log(nextbig(12))
console.log(nextbig(517))
console.log(nextbig(2017))
Here is the idea:
var a = [4, 5, 6];
for (var m = 0; m < a[0]; m++)
for (var n = 0; n < a[1]; n++)
for (var p = 0; p < a[2]; p++)
console.log(`${m} + ${n} + ${p} = ${m+n+p}`);
Live Copy:
// This just tells the Stack Snippets in-snippet console not
// to throw away entries once it reaches a max (the default max
// is just the last 50 logs).
console.config({maxEntries: Infinity});
var a = [4, 5, 6];
for (var m = 0; m < a[0]; m++)
for (var n = 0; n < a[1]; n++)
for (var p = 0; p < a[2]; p++)
console.log(`${m} + ${n} + ${p} = ${m+n+p}`);
/* This just makes the console take up the full output area */
.as-console-wrapper {
max-height: 100% !important;
}
The code would get longer if the array a has more indexes. Could the code be shorten using Array.map or filter or a function?
We can do this without taking up massive amounts of memory, and fairly simply, by using recursion:
const process = (array, n, numbers) => {
if (n < array.length) {
// Not done yet, recurse once for each number at this level
const max = array[n];
for (let i = 0; i < max; ++i) {
process(array, n + 1, [...numbers, i]);
}
} else {
// Done with this level, process the numbers we got
console.log(`${numbers.join(" + ")} = ${numbers.reduce((s, e) => s + e)}`);
}
}
process([4, 5, 6], 0, []);
Live Copy, with cross-checking against your results to ensure the above does the same thing:
// This just tells the Stack Snippets in-snippet console not
// to throw away entries once it reaches a max (the default max
// is just the last 50 logs).
console.config({maxEntries: Infinity});
function thisSolution() {
const results = [];
const process = (array, n, numbers) => {
if (n < array.length) {
// Not done yet, recurse once for each number at this level
const max = array[n];
for (let i = 0; i < max; ++i) {
process(array, n + 1, [...numbers, i]);
}
} else {
// Done with this level, process the numbers we got
const result = numbers.reduce((s, e) => s + e);
results.push(result);
console.log(`${numbers.join(" + ")} = ${result}`);
}
}
process([4, 5, 6], 0, []);
return results;
}
function yourSolution() {
const results = [];
var a = [4, 5, 6];
for (var m = 0; m < a[0]; m++)
for (var n = 0; n < a[1]; n++)
for (var p = 0; p < a[2]; p++)
results.push(m + n + p);
return results;
}
const thisResult = thisSolution();
const yourResult = yourSolution();
if (thisResult.some((entry, index) => entry !== yourResult[index])) {
console.log("WRONG");
} else {
console.log("RIGHT");
}
/* This just makes the console take up the full output area */
.as-console-wrapper {
max-height: 100% !important;
}
This never goes deep into the stack (a.length + 1 stack frames, to be precise, so four in the example case). It builds up a number of temporary arrays (145 in the example case) that max out at a.length entries, releasing them as soon as they aren't needed anymore (a max of four are retained at any given time). Here's the quick and dirty metrics on that:
let maxStack = 0;
let stack = 0;
let totalArrays = 0;
let maxArrays = 0;
let arrays = 0;
// A wrapper for counting stack frames
const process = (...args) => {
if (++stack > maxStack) {
maxStack = stack;
}
const result = process2(...args);
--stack;
return result;
};
const process2 = (array, n, numbers) => {
if (n < array.length) {
// Not done yet, recurse once for each number at this level
const max = array[n];
for (let i = 0; i < max; ++i) {
++totalArrays;
if (++arrays > maxArrays) {
maxArrays = arrays;
}
process(array, n + 1, [...numbers, i]);
--arrays;
}
} else {
// Done with this level, process the numbers we got
//console.log(`${numbers.join(" + ")} = ${numbers.reduce((s, e) => s + e)}`);
}
}
process([4, 5, 6], 0, []);
++maxArrays; // To account for the one in the last argument above
++totalArrays; // "
console.log(`Max stack: ${maxStack}, max arrays: ${maxArrays}, total arrays: ${totalArrays}`);
It's easier if you break it down. First, you need to create a series per every element of your array.
let series = num => Array.from({ length: num + 1 }, (n, i) => i); //creates an array with nums from 0 to num.
That's the first part of your question. Then you need to do a cross product of your series.
Basically for two series [1, 2, 3] and [1, 2, 3, 4] you'll end up with a set of 12 elements:
[2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7]
And for that you could do:
let crossProduct = (a1, a2) => Array.prototype.concat.call(...a1.map(n1 => a2.map(n2 => n1 + n2)));
Now all you need to do is have a crossProduct for every series.
let final = numbers.map(series).reduce(crossProduct);
And there you have it:
let numbers = [4, 5, 6];
let series = num => Array.from({ length: num + 1 }, (n, i) => i);
let crossProduct = (a1, a2) => Array.prototype.concat.call(...a1.map(n1 => a2.map(n2 => n1 + n2)));
let final = numbers.map(series).reduce(crossProduct);
console.log(final);
Edit: If it's from 0 to the number before (e.g. 4 is [0, 1, 2, 3]) then just take the + 1 in the series function.
2nd Edit: Less objects created for your crossProduct:
let crossProduct = (a1, a2) => {
let resultingSet = [];
for(let i = 0; i < a1.length; i++)
for(let j = 0; j < a2.length; j++)
resultingSet.push(a1[i] + a2[j]);
return resultingSet;
} //only one array is created
And if you want to avoid having the series on memory all the time:
let numbers = [4, 5, 6];
let series = function* (num){
for(let i = 0; i < num; i++){
yield i;
}
}
let crossProduct = (set, num) => {
let resultingSet = [];
for(let i = 0; i < set.length; i++){
for(let j of series(num)){
resultingSet.push(set[i] + j);
}
}
return resultingSet;
}
let final = numbers.reduce(crossProduct, [0]);
console.log(final);
Another solution that doesn't consume alot of memory and fairly efficient is by using an array that represnt the value of the indexes and update it each iteration.
first you create an array that represent in each element the amount of iterations you need to run in order to update the indexes respectively for example for this array [1, 2, 3 ,4 ,5] you will get:
[280, 140, 20, 5, 1] this means that index[0] will be updated each 280 iterations, index[1] will be updated each 140 iterations and so on..
totally you will run arr[n] * arr[n-1] * arr[n-2] * .... * arr[0] iterations as you did with ordinary nested for loop.
var arr = [1, 2, 7, 4, 5];
var indexes = Array.from({length: arr.length}, () => 0);
iterationsPerElement = arr.map((_, i) => arr.slice(i+1).reduce((acc, elem) => acc * elem, 1));
var totalIterations = iterationsPerElement[0] * arr[0];
for(var iteration = 1; iteration <= totalIterations; iteration++) {
// sum those indexes
console.log(`sum = ${indexes.reduce((acc, index) => acc + index, 0)}`);
// update indexes
for(i = 0; i < indexes.length; i++) {
if(iteration % iterationsPerElement[i] == 0) {
indexes[i]++;
// empty the indexes on the right
for(var j=i+1; j <indexes.length; j++) {
indexes[j] = 0;
}
}
}
}
I have an integer X and a list of all the factors of X. I want to output the ratio between X and a factor, and for each time set X to that ratio. I want this algorithm to continue till the ratio is bigger than or equal to 1.
For example: X = 36.
All factors (but 1 and 36): 2, 3, 4, 6, 9, 12, 18,
Algorithm: 36 / 2 = 18 --> 18 / 3 = 6 --> 6 / 4 = 1.5 --> 1.5 / 6 < 1 --> Stop
Output: [18, 6, 1.5]. Question:
How do I get this output?
What i have written:
var arr = [];
for (var i = 2; i < X; i++) {
if (X % i == 0) {
arr.push(i);
}
}
var temp = [];
var index = 0;
while (X / arr[index] >= 1) {
index += 1;
X = X / arr[index];
temp.push(X / arr[index]);
}
var arr = [];
var X = 36
for (var i = 2; i < X; i++) {
if (X % i == 0) {
arr.push(i);
}
}
var temp = arr.reduce((acc, item, index) => {
if(!(X/item < 1)){
acc.push(X/item)
X = X/item;
}
return acc;
}, [])
console.log(temp)
You could calculate the first value before you go into the while loop an check the asssigned x. If the value passes the condition, you could push that value to the result array and increment the index and calculate a new value.
function fn(x) {
var array = [], // declare all variable on top
i,
result = [];
for (var i = 2; i < x; i++) {
if (x % i == 0) {
array.push(i);
}
}
i = 0; // prepare index for looping
x /= array[i]; // take a first possible value
while (x >= 1) { // check value
result.push(x); // push value
i++; // increment index
x /= array[i]; // take the next value for checking
}
return result;
}
console.log(fn(36))
A bit shorter with Array#every
function fn(x) {
var array = [], // declare all variable on top
i,
result = [];
for (var i = 2; i < x; i++) {
if (x % i == 0) {
array.push(i);
}
}
array.every(v => (x /= v) >= 1 && result.push(x));
return result;
}
console.log(fn(36))
Your question is a little bit confuse. Is this what you want?
Basically, I update the factor after each iteration (if >= 1) and store into an array the output.
// Generate a range of integers (starting at 2, and we should not including the input)
// get only values divisible by the input (filter)
const generateRange = (input) => {
return Array.from({length: (input - 2)}, (v, k) => k + 2).filter(i => {
return input % i === 0;
})
}
const divideFactors = (input) => {
const list = generateRange(input) // filtered range
let output = []
let factor = input
for (const item of list) {
let ratio = factor / item
if (ratio < 1) { //if ratio < 1, break the loop
break;
}
output.push(ratio) // update output array with new ratio
factor = ratio; // update factor variable with current ratio
}
return output
}
console.log(divideFactors(36))
More info:
Array.from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
For of: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of