Breaking An Integer Up Into Chunks, Functionally
Solution 1:
Here's another way you can do it using a recursive procedure and a little helper quotrem
– which given a numerator n
, and a denominator d
, returns [<quotient>, <remainder>]
constquotrem = (n, d) => [n / d >> 0, n % d]
constbreakup = (n, [x,...xs]) => {
if (x === undefined) {
return [n]
}
else {
let [q, r] = quotrem(n, x)
return [r, ...breakup(q, xs)]
}
}
console.log(breakup(1000, [8, 8, 8]))
// [ 0, 5, 7, 1 ]console.log(breakup(100000000, [1000, 60, 60, 24]))
// [ 0, 40, 46, 3, 1 ]
If you're not particularly comfortable with the destructured array, you can add a few more helpers (isEmpty
, head
, and tail
) to interact with the array in a more explicit way
constisEmpty = xs => xs.length === 0consthead = xs => xs[0]
consttail = xs => xs.slice(1)
constquotrem = (n, d) => [n / d >> 0, n % d]
constbreakup = (n, xs) => {
if (isEmpty(xs)) {
return [n]
}
else {
let [q, r] = quotrem(n, head(xs))
return [r, ...breakup(q, tail(xs))]
}
}
console.log(breakup(1000, [8, 8, 8]))
// [ 0, 5, 7, 1 ]console.log(breakup(100000000, [1000, 60, 60, 24]))
// [ 0, 40, 46, 3, 1 ]
Solution 2:
This feels like a job for
reduce
, though I don't see how.
Everything that iterates an array can be done with reduce
:-)
We need to pass two things through (for the accumulator): the number that we still have the break, and the list of results. We can use ES6 destructuring and an array as a tuple:
functionbreakup(n, units) {
const [n, res] = units.reduce(([n, res], u) => {
const q = n % u;
res.push((n-q) / u);
return [q, res];
}, [n, units]);
return [n, ...res];
}
But that push
is still ugly. Not only because it mutates (where we could have used concat
as well), but what we really want is a function that abstracts this away. Unfortunately these don't exists in JS - we'd be looking for a scan or mapping accumulation. We could write
functionbreakup(n, units) {
const [rest, res] = units.mapAccum((n, u) => {
const q = n % u;
return [q, (n-q) / u];
}, [n, units]);
return [...res, rest];
}
functionbreakup(n, units) {
const mods = units.scan((n, u) =>Math.floor(n/u), units);
return mods.map((q, i) => i<units.length ? q % units[i] : q);
}
I'll leave the (functional, efficient, readable, etc) implementation of those as an exercise to the reader.
Solution 3:
I would suggest this code:
constbreakup = (n, l) =>
l.reduce( ([n, ...res], p) => ([(n - n % p) / p, n % p, ...res]), [n])
.reverse();
// Demo callconsole.log(breakup(100000000, [1000, 60, 60, 24]));
Post a Comment for "Breaking An Integer Up Into Chunks, Functionally"