Reputation: 7739
I am working through this coding challenge on Free Code Camp
We'll pass you an array of two numbers.
Return the sum of those two numbers and all numbers between them.
The lowest number will not always come first.
They suggest to use Math.max(), Math.min(), Array.reduce()
, however I began working through a solution which did not use any of those methods—but soon discovered maybe I should have because my version began to look a little clunky.
function sumAll(arr){
var index0 = arr[0], index1 = arr[1], counter = 0, sum = 0, val;
if(index0 < index1){
counter += index0;
while(counter <= index1){
val = index0++;
sum += val;
counter++;
}
} else if(index0 > index1){
counter = 1;
counter += index0;
while(counter >= index1){
val = index1 + 1;
sum += val;
counter--;
}
}
return sum;
}
Basically this works save for when you try:
sumAll([10, 5]) //I get 42, rather than 45
So my two questions are the following:
Am I correct in the fact it's getting clunky? And should I have used the aforementioned methods which were recommended? I think I just got excited when stuff when I got things to work but now I feel I am going down a rabbit hole with another potential condition..
Thanks in advance!
Upvotes: 1
Views: 1971
Reputation: 707386
Here's a bit faster version that takes advantage of the fact that you don't have to actually add every single sequential number in a sequence, but you can calculate that sum based on the start and end point:
function sumAll(args) {
var min = Math.min.apply(Math, args),
max = Math.max.apply(Math, args);
return min + ((max - min) * ((max + min + 1) / 2));
}
And, here's a test bed: https://jsfiddle.net/jfriend00/rh75gesc/ which compares it to the old fashioned way for accuracy.
For pure performance (not code brevity), it's probably better to just compare the two values rather than make two function calls:
function sumAllFaster(args) {
var min, max;
if (args[0] < args[1]) {
min = args[0];
max = args[1];
} else {
min = args[1];
max = args[0];
}
return min + ((max - min) * ((max + min + 1) / 2));
}
If you test this against the @NenadVracar answer and include some large ranges, this last version is up to 100 times faster. The longer the range, the more of a speed difference. Even with short ranges, it is 3-4x faster. Timed tests here: https://jsfiddle.net/jfriend00/5daztnky/.
Here's a slightly faster version:
function sumAllFastest(args) {
var diff = args[0] < args[1] ? args[1] - args[0] : args[0] - args[1];
return (1 + diff) * ((args[0] + args[1]) / 2)
}
Upvotes: 4
Reputation: 5955
I'm pretty sure that, when saying: "an array of numbers", he/she didn't mean an Array Object containing those two numbers. So I offer you this Spartan JS:
function sum_range(x,y){ return( 1 + ( x < y ? y - x : x - y ) ) * (x + y) / 2; }
p.s.: It can be found on my FB timeline.
But even than, you are reassured that the supposed array will contain only two peripheral numbers of the range;
So it's all the same. The change is in the way of passing arguments to the function, e.g.:
console.log( sum_range( arr[0], arr[1] ) );
v.s.:
console.log( sum_range( 10, 5 ) );
Upvotes: 1
Reputation: 677
An intuitive way to solve this would be to:
Something like this:
sumAll = function(arr) {
var low_bound = Math.min.apply(Math, arr);
var up_bound = Math.max.apply(Math, arr);
result = 0;
for (i=low_bound;i<=up_bound;i++){
result += i;
}
return result
}
Upvotes: 0
Reputation: 318212
Here's a bit slower version, but it's in ES6, which is cool
function sumAll(arr, n=1){
const [min, max] = arr.sort();
return Array(max+n).fill(0,min-n,max+n).reduce((a,b,i) => a+i);
}
Upvotes: 2
Reputation: 122047
You could use min
, max
and one loop
var sumAll = function(arr) {
var sum = 0,
min = Math.min.apply(null, arr),
max = Math.max.apply(null, arr);
for (var i = min; i <= max; i++) {
sum += i;
}
return sum;
}
console.log(sumAll([10, 5]))
Upvotes: 2