I have a number N e.g. 100 and I want to divide it into n parts (e.g. 10 parts)
Doing this linearly is trivial - N/n and I get 10 parts each of the value 10.
However, I would like to do this so that the parts are unequal and increase exponentially. E.g.
10, 30, 60 so the total is 100.
How can I write this as a javascript function?
function returnParts(desiredTotal, numParts) {
...
return parts ///return an array of parts
}
CodePudding user response:
This is a Math problem. Once you solve it, implementing this with JS or any other language is just calculation.
So you want K numbers summing to T. However they will increase exponentially. Not so clear but from your given example lets assume our exponential series to be
T = x 2x 4x 8x ... 2^(n-1) x
We can apply summing series trick here like
2T = 2x 4x 8x ... 2^n x
Now;
2T = 2x 4x 8x ... 2^x
T = x 2x 4x 8x ... 2^(n-1) x
(-)__________________________________
T = 2^n x - x = (2^n - 1) x
So;
T
x = _________
2^n - 1
The JS part.
function part(n,target){
var x = target / (2**n-1);
return Array.from({length:n}, (_,i) => x*2**i);
}
var result = part(6,100),
sum = result.reduce((p,c) => p c);
console.log(result,sum);
CodePudding user response:
The function is simple enough, when you allow floating point numbers:
function getNums(n,f,tot){
let x=1;
const arr=[...new Array(n)]
.map(c=>x*=f);
const mul=tot/arr.reduce((a,c)=>a c);
return arr.map(v=>mul*v)
}
console.log(getNums(3, 1.5, 100))
In order to get a unique result you need to specify the desired count n of numbers, the factor between the numbers f and the total tot the individual numbers must add up to.
And here is an adapted solution for integers:
function getNums(n,f,tot){
let x=1,res;
const arr=[...new Array(n)]
.map(c=>x*=f);
const mul=tot/arr.reduce((a,c)=>a c);
res=arr.map(v=>Math.round(mul*v));
res[res.length-1]-=res.reduce((a,c)=>a c)-tot;
return res
}
const ar=getNums(3, 1.5, 100);
console.log(ar,ar.reduce((a,c)=>a c))
CodePudding user response:
This should do it. The exponential function is: A^numParts = desiredTotal. We first solve for A then push the values calculated values into the array. This works because the integral of an exponential function is the exponential function.
function returnParts (desiredTotal, numParts) {
var a = Math.pow(desiredTotal, 1/numParts)
var parts = []
for (var j = 0; j < numParts; j ) {
var part = Math.pow(a, j 1) - Math.pow(a, j)
parts.push(part)
}
return parts
}
For example:
var results = returnParts(1000, 3)
console.log(results)
//
//returns [9.999999999999998, 89.99999999999997, 909.9999999999994]
// which is equal to ~1000
//
