These days I would want to separate the process of generating the next number, from the process of totalling them up.
The next number can be generated using a generator function, that just yields the next number before increasing the value;
function* oddNumbers(limit) {
let index = 1;
while (index <= limit) {
yield index;
index += 2;
}
}
One way to then handle that generator is to assign the function to a generating variable, and call .next()
const nextNumGenerator = oddNumbers(25);
let num = nextNumGenerator.next().value;
let total = 0;
while (num) {
total += num;
num = nextNumGenerator.next().value;
}
That works, but there’s a lot of complexity in there. Simpler is to use for...of
which natively understands how to handle generators.
let total = 0;
for (let num of oddNumbers(25)) {
total += num;
}
Even simpler than that though is to use the spread syntax:
let total = [...oddNumbers(25)]
.reduce((sum, value) => sum += value);
But it’s inefficient to create a whole array of values when we are only going to reduce them down to a total.
Let’s instead use a generator that gives us the total value of summed odd numbers:
function* oddNumbersTotal(limit) {
let index = 1;
for (let total = 0; index <= limit; index += 2) {
total += index;
yield total;
}
}
let total = 0;
for (total of oddNumbersTotal(25)) {}
But why are we iterating over all of the previous totals? Surely it’s easier to just calculate the value straight out.
How would we calculate the total of odd numbers? We can use two sets of odd numbers to figure this out.
S = 1 + 3 + ... + n-2 + n;
S = n + n-2 + ... + 3 + 1;
S2 = (n+1) + (n+1) + ... + (n+1) + (n+1)
How many of those (n+1)'s are there?
When n is 5, there would be three of them (1, 3, 5).
When n is 9, there would be 5 of them, so overall there are (n+1)/2 of them.
S2 = (n+1) * (n+1) / 2
S = 1/2 (n+1) * (n+1) / 2
So, if we want the sum of odd numbers from 1 to 25, all we need to do is to just purely calculate the total using that formula.
function oddNumbersTotal(limit) {
return 0.5 * (limit + 1) * (limit + 1) / 2;
}
const total = oddNumbersTotal(25);
Which could be simplified even further.
S = 1/2 (n+1) * (n+1) / 2
S = (n+1) / 2 * (n+1) / 2
S = ((n+1)/2) ^ 2
function oddNumbersTotal(limit) {
// using the ((n+1)/2)² formula
return Math.pow((limit + 1) / 2, 2);
}
const total = oddNumbersTotal(25);
There’s no need to involve loops or generating arrays of numbers when all you need is the total.