Javascript: adjacent Elements Product algorithm - javascript

I'm trying to solve a basic javascript algorithm and i'm kinda stuck, here is the question:
Given an array of integers, find the pair of adjacent elements that
has the largest product and return that product.
Example
For inputArray = [3, 6, -2, -5, 7, 3], the output should be
adjacentElementsProduct(inputArray) = 21.
7 and 3 produce the largest product.
Here is my code, i can't find the problem but in the tests it says that it returns null:
function adjacentElementsProduct(inputArray) {
var cb;
for(var i=0;i<inputArray.length;i++){
if(inputArray[i] !== inputArray[inputArray.length-1]){
if(inputArray[i]*inputArray[i+1] > cb){
cb = inputArray[i]*inputArray[i+1];
}
}
}
return cb;
}
What is my problem and what i need to change?

What you ultimately want to do is iterate through the array excluding the last member, and compare a product of each current item with its next adjacent member to that of the largest one found thus far.
You can use .slice() and .reduce() for this.
function adjacentElementsProduct(arr) {
return arr.slice(0, -1)
.reduce((max, n, i) => Math.max(max, n * arr[i + 1]), -Infinity)
}
console.log(adjacentElementsProduct([3, 6, -2, -5, 7, 3]));
An alternate solution would be to create an array of products using .map() after doing the same .slice(), and pass that array's members to Math.max.
function adjacentElementsProduct(arr) {
return Math.max(...arr.slice(0, -1).map((n, i) => n * arr[i + 1]))
}
console.log(adjacentElementsProduct([3, 6, -2, -5, 7, 3]));

The problem with your code is you never initialized cb. So the comparison with cb is always invalid. Here is the correct version of your code -
function adjacentElementsProduct(inputArray) {
var cb = Number.NEGATIVE_INFINITY;
for(var i=0;i<inputArray.length-1;i++){
if(inputArray[i]*inputArray[i+1] > cb){
cb = inputArray[i]*inputArray[i+1];
}
}
return cb;
}
console.log(adjacentElementsProduct([3, 6, -2, -5, 7, 7]))

Since you need to use pairs of elements - you can just run through it and keep store maximum product value, something like this:
function adjacentElementsProduct(items) {
var product = 0;
for (var i = 0; i < items.length - 1; i++) {
product = Math.max(product, items[i] * items[i + 1]);
}
return product;
}
console.log(adjacentElementsProduct([3, 6, -2, -5, 7, 3]));

Using reduce we can simplify the amount of code.
var a = [3, 6, -2, -2, 7, 3].reduce(function(a, b, i, arr){
if (b*arr[i-1] > a)
{
a = b*arr[i-1];
}
return a;
})
console.log(a)

First of all, you could iterate from index 1 to the end and use i - 1 and i for adjacent elements. Then you could check if you are in iteration one and take the value or if the multiplication is greater then the old value, then assing the greater product.
function adjacentElementsProduct(inputArray) {
var cb, i;
for (i = 1; i < inputArray.length; i++) {
if (i === 1 || inputArray[i - 1] * inputArray[i] > cb) {
cb = inputArray[i - 1] * inputArray[i];
}
}
return cb;
}
console.log(adjacentElementsProduct([3, 6, -2, -5, 7, 3]));

More generic solution:
This will work for every array with negatives and non negatives numbers.
int adjacentElementsProduct(int[] inputArray) {
int length = inputArray.Length;
int max = Number.NEGATIVE_INFINITY;
for (int i = 0; i < length - 1; i++ ) {
max = Math.Max(max, inputArray[i] * inputArray[i+1]);
}
return max;
}

int adjacentElementsProduct(std::vector<int> inputArray) {
int n=inputArray.size();
int p=1;
int maxp=inputArray[0]*inputArray[1];
for(int i=0;i<n-1;i++){
p=inputArray[i]*inputArray[i+1];
if(p>maxp){
maxp=p;
}
}
return maxp;
}

Here is how you will do that in Python:
def adjacentElementsProduct(inputArray):
max = inputArray[0]* inputArray[1]
for i in range(0, len(inputArray)-1):
if inputArray[i] * inputArray[i+1] > max :
max = inputArray[i] * inputArray[i+1]
i+1
else:
i+1
return max
Or you can do it in one line like:
def adjacentElementsProduct(inputArray):
return max([inputArray[i] * inputArray[i+1] for i in range(len(inputArray)-1)])

function largetProduct(inputArray) {
let pairs=[];
for(var i = 0;i<inputArray.length ;i+=2){
pairs.push(inputArray.slice(i,i+2))
}
let products = pairs.map(v=> v[0]*v[1] || 1);
return (Math.max.apply(0,products));
}

Related

How do i return new array with removing one of the elements based on condition [duplicate]

I have a number array [2, 1, 3, 4, 5, 1] and want to remove the smallest number in the list. But somehow my IF statement gets skipped.
I checked and by itself "numbers[i + 1]" and "numbers[i]" do work, but "numbers[i + 1] < numbers[i]" doesn't...
function removeSmallest(numbers) {
var smallestNumberKEY = 0;
for (i = 0; i <= numbers.lenths; i++) {
if (numbers[i + 1] < numbers[i]) {
smallestNumberKEY = i + 1;
}
}
numbers.splice(smallestNumberKEY, 1);
return numbers;
}
document.write(removeSmallest([2, 1, 3, 4, 5, 1]));
You have a typo in your code, array doesn't have lenths property
function removeSmallest(numbers) {
var smallestNumberKEY = 0;
for (var i = 0; i < numbers.length - 1; i++) {
if (numbers[i + 1] < numbers[i]) {
smallestNumberKEY = i + 1;
numbers.splice(smallestNumberKEY, 1);
}
}
return numbers;
}
document.write(removeSmallest([2, 1, 3, 4, 5, 1]));
But your algorithm wont work for another array, e.g [5, 3, 1, 4, 1], it will remove a value 3 too.
You can find the min value with Math.min function and then filter an array
function removeSmallest(arr) {
var min = Math.min(...arr);
return arr.filter(e => e != min);
}
You can use Array#filter instead
function removeSmallest(arr) {
var min = Math.min.apply(null, arr);
return arr.filter((e) => {return e != min});
}
console.log(removeSmallest([2, 1, 3, 4, 5, 1]))
Short one liner. If the smallest value exist multiple times it will only remove ONE. This may or may not be what you want.
const result = [6,1,3,1].sort().filter((_,i) => i) // result = [1,3,6]
It works by sorting and then creating a new array from the items where indeces are truthy(anything but 0)
another solution with splice and indexOf:
array = [2, 1, 3, 4, 5, 1];
function replace(arr){
arr = arr.slice(); //copy the array
arr.splice( arr.indexOf(Math.min.apply(null, arr)),1)
return arr;
}
document.write( replace(array) ,'<br> original array : ', array)
edit : making a copy of the array will avoid the original array from being modified
"Short" solution using Array.forEach and Array.splice methods:
function removeSmallest(numbers) {
var min = Math.min.apply(null, numbers);
numbers.forEach((v, k, arr) => v !== min || arr.splice(k,1));
return numbers;
}
console.log(removeSmallest([2, 1, 3, 4, 5, 1])); // [2, 3, 4, 5]
This is a proposal with a single loop of Array#reduce and without Math.min.
The algorithm sets in the first loop min with the value of the element and returns an empty array, because the actual element is the smallest value and the result set should not contain the smallest value.
The next loop can have
a value smaller than min, then assign a to min and return a copy of the original array until the previous element, because a new minimum is found and all other previous elements are greater than the actual value and belongs to the result array.
a value greater then min, then the actual value is pushed to the result set.
a value equal to min, then the vaue is skipped.
'use strict';
var removeSmallest = function () {
var min;
return function (r, a, i, aa) {
if (!i || a < min) {
min = a;
return aa.slice(0, i);
}
if (a > min) {
r.push(a);
}
return r;
}
}();
document.write('<pre>' + JSON.stringify([2, 1, 3, 2, 4, 5, 1].reduce(removeSmallest, []), 0, 4) + '</pre>');
I like this oneliner: list.filter(function(n) { return n != Math.min.apply( Math, list ) })
check it out here: https://jsfiddle.net/rz2n4rsd/1/
function remove_smallest(list) {
return list.filter(function(n) { return n != Math.min.apply( Math, list ) })
}
var list = [2, 1, 0, 4, 5, 1]
console.log(list) // [2, 1, 0, 4, 5, 1]
list = remove_smallest(list)
console.log(list) // [2, 1, 4, 5, 1]
list = remove_smallest(list)
console.log(list) // [2, 4, 5]
I had to do this but I needed a solution that did not mutate the input array numbers and ran in O(n) time. If that's what you're looking for, try this one:
const removeSmallest = (numbers) => {
const minValIndex = numbers.reduce((finalIndex, currentVal, currentIndex, array) => {
return array[currentIndex] <= array[finalIndex] ? currentIndex : finalIndex
}, 0)
return numbers.slice(0, minValIndex).concat(numbers.slice(minValIndex + 1))
}
function sumOfPaiars(ints){
var array = [];
var min = Math.min(...ints)
console.log(min)
for(var i=0;i<ints.length;i++){
if(ints[i]>min){
array.push(ints[i])
}
}
return array
}
If you only wish to remove a single instance of the smallest value (which was my use-case, not clear from the op).
arr.sort().shift()
Here is a piece of code that is work properly but is not accepted from codewars:
let numbers = [5, 3, 2, 1, 4];
numbers.sort(function numbers(a, b) {
return a - b;
});
const firstElement = numbers.shift();

Non-negative array subtraction in JavaScript

The answer found here is so close to what i am looking for but not quite there. What I am looking is I have an array of integers, and a value that I need to subtract from across said array. i want to zero out each index before moving on to the next. I don't want any numbers less than 0 nor do i want any decimals.. so, for subtractFromSet([4, 5, 6, 7, 8], 25) instead of returning:
[0,0,0.666666666666667,1.666666666666666,2.666666666666666]
I want:
[0,0,0,0,5]
You can loop until there is nothing left to subtract.
function subtractFromArr(arr, val){
const res = [...arr];//copy
for(let i = 0; i < res.length && val > 0; i++){
const take = Math.min(res[i], val);
res[i] -= take;
val -= take;
}
return res;
}
console.log(subtractFromArr([4, 5, 6, 7, 8], 25));
You can loop through the array "number" of times, while subtracting 1 from the current index and moving to the next index when index is equal to 0
function subtractFromSet(array, number) {
var i = 0;
do {
array[i]--;
number--;
if(array[i] == 0) i++;
} while (number != 0);
return array;
}
subtractFromSet([4, 5, 6, 7, 8], 25);

JavaScript: Writing this solution using higher order functions

I worked on a problem where you are given an array of numbers and a target sum, and it's your job to find a pair of numbers that sum up to the target number. Here was my solution using simple nested for loops:
function findPairForSum(integers, target) {
var output = [];
for (var i = 0; i < integers.length; i++) {
for (var j = 0; j < integers.length; j++) {
if (i !== j && integers[i] + integers[j] === target) {
output.push(integers[i], integers[j]);
return output;
}
}
}
return 'not possible';
}
findPairForSum([3, 34, 4, 12, 5, 2], 9); // --> [4, 5]
My question is, is there a cleaner way to write this solution using higher order functions (perhaps forEach?)
Here was my attempt to use forEach:
function findPairForSum(integers, target) {
var output = [];
integers.forEach(function(firstNum) {
integers.forEach(function(secondNum) {
if (firstNum + secondNum === target) {
output.push(firstNum, secondNum);
}
})
})
if (output === []) {
return 'not possible';
}
return output;
}
findPairForSum([3, 34, 4, 12, 5, 2], 9); // --> [ 4, 5, 5, 4 ]
I tried putting a return after the two pushes, but it did not return anything. So instead, I put the return at the very end.
Why won't it return after the initial two pushes? I want it to stop right there, and only push the two numbers. Instead, by putting the return at the end, it pushed 4 numbers. It should be [4,5] but I got something like [4,5,5,4].
Any advice and help would be much appreciated!
Assume we have the following set of numbers, and we must find a subset of 2 numbers whose sum is 9:
Numbers: 4, 5, 6
Your current code iterates both with i and j from 0 to length. This means that the following iterations match the condition:
Indices: 0, 1, 2
Numbers: 4, 5, 6 // (i) (j)
---------------- // ↓ ↓
i j // Numbers[0] + Numbers[1] === 9
j i // Numbers[1] + Numbers[0] === 9
As you can see, the numbers 4 and 5 are matched twice, in 2 iterations:
i === 0 && j === 1
i === 1 && j === 0
You can avoid this by making sure one simple condition is met:
j must at all times be greater than i
This condition can be met met by initializing j with i + 1 in the inner for loop:
for (var i = 0; i < integers.length; i++) {
for (var j = i + 1; j < integers.length; j++) {
// ...
}
}
This way, j can never be 0 when i is 1, because the inner for-loop will run to completion before i is ever incremented once more. Once that happens, a brand new inner for-loop is created, in which j is again set to i + 1. The following diagram is the result:
Indices: 0, 1, 2
Numbers: 4, 5, 6
----------------
i j
X i // ← j can never be 0 if (i === 1),
// so the same set is never evaluated twice.
In other words, only the following combinations for i and j are checked at most:
Indices: 0, 1, 2
----------------
i j
i j
i j
is there a cleaner way to write this solution using higher order functions (perhaps forEach?)
A for loop is actually a fine solution for your use-case. They allow you to break early - after the first time you find a valid pair of numbers. forEach or other array iterator functions on the other hand will always continue until all set indices are visited.
You are actually breaking early in your first example with the statement return output;
When you use forEach on a set of numbers with multiple valid sets, you'll always get back all numbers involved:
Indices: 0, 1, 2, 3
Numbers: 4, 5, 6, 3 // (i) (j)
------------------- // ↓ ↓
i j // Numbers[0] + Numbers[1] === 4 + 5 === 9
i j // Numbers[2] + Numbers[3] === 6 + 3 === 9
forEach, map, reduce and the like do not allow you to break early. The following snippet demonstrates this issue of the diagram above:
function findPairForSum(integers, target) {
var output = [];
integers.forEach(function(firstNum, i) {
// slice(i + 1) has the same effect as for (var j = i + 1; ...)
integers.slice(i + 1).forEach(function(secondNum, j) {
if (firstNum + secondNum === target) {
// There is no way here to stop the iteration of either
// forEach call... T_T
output.push(firstNum, secondNum);
}
});
})
if (output.length) {
return output;
}
return 'not possible';
}
console.log(findPairForSum([4, 5, 6, 3], 9)); // --> [4, 5, 6, 3]
This is why I highly recommend sticking with the for loops for this specific use case. With for loop you can simply return as you already did as soon as you encounter a valid set of numbers:
function findPairForSum(integers, target) {
for (var i = 0; i < integers.length; i++) {
for (var j = i + 1; j < integers.length; j++) {
if (integers[i] + integers[j] === target) {
return [integers[i], integers[j]];
}
}
}
return 'not possible';
}
console.log(findPairForSum([4, 5, 6, 3], 9)); // --> [4, 5]
This could be your solution:
function findPairForSum(arr, sum) {
var pairs = [];
arr.forEach(n1 => {
var n2 = arr.find(n2 => n1 + n2 == sum)
if (n2) pairs.push([n1, n2]);
});
return pairs;
}
var sums = findPairForSum([3, 34, 4, 12, 6, 2], 9);
console.log(sums)
The problem is, you iterate from the start of the array for the inner loop. You could use a copy which starts at the index of the outer loop plus one and exit early on a found value.
But this does not solves the problem with multiple pairs. The result is simply wrong.
function findPairForSum(integers, target) {
var output = [];
integers.forEach(function(firstNum, i) {
integers.slice(i + 1).some(function(secondNum) {
if (firstNum + secondNum === target) {
output.push(firstNum, secondNum);
return true;
}
});
});
return output.length && output || 'not possible';
}
// console.log(findPairForSum([3, 34, 4, 12, 5, 2], 9));
console.log(findPairForSum([3, 34, 4, 4, 12, 5, 2, 4, 5], 9));
For a solution, you need to remember which pairs are used. This approach works with only one loop and a hash table for counting missing values.
If a pair is found, the counter is decremented and the two values are pushed to the result set.
function findPairForSum(integers, target) {
var hash = Object.create(null),
output = [];
integers.forEach(function(value) {
if (hash[value]) {
output.push(target - value, value);
hash[value]--;
return;
}
hash[target - value] = (hash[target - value] || 0) + 1;
});
return output.length && output || 'not possible';
}
console.log(findPairForSum([3, 34, 4, 4, 12, 5, 2, 4, 5], 9));
This is expected, since you didn't compare the indexes.
This inner array should only loop through the indexes which larger than the outer index.
You can achieve this by using the 2nd parameter, index, in forEach's callback function:
const ints = [3, 34, 4, 12, 5, 6, 2];
function findPairForSum(integers, target) {
let result;
integers.forEach((val1, idx1) => {
integers.forEach((val2, idx2) => {
if (idx1 < idx2 && val1 + val2 === target) {
result = [val1, val2];
}
})
})
return result;
}
console.log(findPairForSum(ints, 9));
Use can reduce your array into another which has sum equals target value:
const ints = [3, 34, 4, 12, 6, 2];
const value = 9;
const resp = ints.reduce((acc, ele, idx, self) => {
let found = self.find(x => x + ele == value)
return found ? [found, ele] : acc;
}, []);
console.log(resp); // [3, 6]
You can use Array.prototype.some which will stop execution as soon as the condition becomes true. See below code.
function findPairForSum(arr, sum) {
var pairs = [];
arr.some(n1 => {
var n2 = arr.find(n2 => n1 + n2 == sum)
if (n2) {
pairs.push(n1, n2); return true;
};
return false;
});
return pairs.length > 0 ? pairs : "not possible";
}
console.log(findPairForSum([3, 34, 4, 12, 7, 2], 9));

Find Missing Numbers from Unsorted Array

I found this JavaScript algorithm excercise:
Question:
From a unsorted array of numbers 1 to 100 excluding one number, how will you find that number?
The solution the author gives is:
function missingNumber(arr) {
var n = arr.length + 1,
sum = 0,
expectedSum = n * (n + 1) / 2;
for (var i = 0, len = arr.length; i < len; i++) {
sum += arr[i];
}
return expectedSum - sum;
}
I wanted to try and make it so you can find multiple missing numbers.
My solution:
var someArr = [2, 5, 3, 1, 4, 7, 10, 15]
function findMissingNumbers(arr) {
var missingNumbersCount;
var missingNumbers = [];
arr.sort(function(a, b) {
return a - b;
})
for(var i = 0; i < arr.length; i++) {
if(arr[i+1] - arr[i] != 1 && arr[i+1] != undefined) {
missingNumbersCount = arr[i+1] - arr[i] - 1;
for(j = 1; j <= missingNumbersCount; j++) {
missingNumbers.push(arr[i] + j)
}
}
}
return missingNumbers
}
findMissingNumbers(someArr) // [6, 8, 9, 11, 12, 13, 14]
Is there a better way to do this? It has to be JavaScript, since that's what I'm practicing.
You could use a sparse array with 1-values at indexes that correspond to values in the input array. Then you could create yet another array with all numbers (with same length as the sparse array), and retain only those values that correspond to an index with a 1-value in the sparse array.
This will run in O(n) time:
function findMissingNumbers(arr) {
// Create sparse array with a 1 at each index equal to a value in the input.
var sparse = arr.reduce((sparse, i) => (sparse[i]=1,sparse), []);
// Create array 0..highest number, and retain only those values for which
// the sparse array has nothing at that index (and eliminate the 0 value).
return [...sparse.keys()].filter(i => i && !sparse[i]);
}
var someArr = [2, 5, 3, 1, 4, 7, 10, 15]
var result = findMissingNumbers(someArr);
console.log(result);
NB: this requires EcmaScript2015 support.
The simplest solution to this problem
miss = (arr) => {
let missArr=[];
let l = Math.max(...arr);
let startsWithZero = arr.indexOf(0) > -1 ? 0 : 1;
for(i = startsWithZero; i < l; i++) {
if(arr.indexOf(i) < 0) {
missArr.push(i);
}
}
return missArr;
}
miss([3,4,1,2,6,8,12]);
Something like this will do what you want.
var X = [2, 5, 3, 1, 4, 7, 10, 15]; // Array of numbers
var N = Array.from(Array(Math.max.apply(Math, X)).keys()); //Generate number array using the largest int from X
Array.prototype.diff = function(a) {
return this.filter(function(i) {return a.indexOf(i) < 0;}); //Return the difference
};
console.log(N.diff(X));
Option 1:
1. create a binary array
2. iterate over input array and for each element mark binary array true.
3. iterate over binary array and find out numbers of false.
Time complexity = O(N)
Space complexity = N
Option 2:
Sort input array O(nLogn)
iterate over sorted array and identify missing number a[i+1]-a[i] > 0
O(n)
total time complexity = O(nlogn) + O(n)
I think the best way to do this without any iterations for a single missing number would be to just use the sum approach.
const arr=[1-100];
let total=n*(n+1)/2;
let totalarray=array.reduce((t,i)=>t+i);
console.log(total-totalarray);
You can try this:
let missingNum= (n) => {
return n
.sort((a, b) => a - b)
.reduce((r, v, i, a) =>
(l => r.concat(Array.from({ length: v - l - 1 }, _ => ++l)))(a[i - 1]),
[]
)
}
console.log(missingNum([1,2,3,4,10]));
Solution to find missing numbers from unsorted array or array containing duplicate values.
Array.prototype.max = function() {
return Math.max.apply(null, this);
};
var array1 = [1, 3, 4, 7, 9];
var n = array1.length;
var totalElements = array1.max(); // Total count including missing numbers. Can use max
var d = new Uint8Array(totalElements)
for(let i=0; i<n; i++){
d[array1[i]-1] = 1;
}
var outputArray = [];
for(let i=0; i<totalElements; i++) {
if(d[i] == 0) {
outputArray.push(i+1)
}
}
console.log(outputArray.toString());
My solution uses the same logic as trincot's answer
The time complexity is O(n)
const check_miss = (n) => {
let temp = Array(Math.max(...n)).fill(0);
n.forEach((item) => (temp[item] = 1));
const missing_items = temp
.map((item, index) => (item === 0 ? index : -1))
.filter((item) => item !== -1);
console.log(missing_items);
};
n = [5, 4, 2, 1, 10, 20, 0];
check_miss(n);

The sum of a range using Javascript

I wish to execute a program with output as :
console.log(range(1, 10));
// → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(range(5, 2, -1));
// → [5, 4, 3, 2]
console.log(sum(range(1, 10)));
// → 55
I am getting an error for array.length.Please find the code below:
var array = [];
function range (arr){
var lower = Math.min(arr[0],arr[1]);
var upper = Math.max(arr[0],arr[1]);
for (var i=lower;i<=upper;i++){
array.push(i);
}
}
function sum(array){
for(var i=0;i < array.length;i++){
var total = total+array[i];
}
}
console.log(sum(range(1, 10)));
I am at begineers level, please do help.
Thanks.
You have a few problems here:
1.) You aren't returning anything in your range function. You need to return the filled array.
2.) You aren't passing the array correctly in the sum function call.
3.) You aren't returning anything in your sum function call.
Without returning any values, you aren't letting your code blocks work with eachother
var array = [];
function range (arr){
var lower = Math.min(arr[0],arr[1]);
var upper = Math.max(arr[0],arr[1]);
for (var i=lower;i<=upper;i++){
array.push(i);
}
return array; // return the array to be used in the sum function
}
function sum(array){
var total = 0; // need to create a variable outside the loop scope
for(var i in array){
total = total+array[i];
}
return total;
}
console.log(sum(range([1,10]))); // pass the array correctly
Note that you need to set the total variable outside the scope of the for-loop within the sum function. That way you can return the final value. Otherwise, it would return undefined.
See the fiddle: https://jsfiddle.net/udyhb95a/
You need to pass an array when calling the range function you defined range([1, 10])
You need to rewrite your sum function
As a side note, there are more efficient ways to compute the sum of a range of elements without iterating on them.
function sum_of_range(start, end) {
return end * (end + 1) / 2 - start * (start + 1) / 2;
}
Edit:
Here is a working sum function
function sum(array) {
var accumulator = 0;
for (var i = 0; i < array.length; ++i)
accumulator += array[i];
return accumulator;
}
Here you declare a function with one parameter as an array
function range (arr){
...
But here you call a function with two arguments as numbers
console.log(range(1, 10));
Use this call function
console.log(range([1, 10]));
And don't use for..in for arrays
for(var i in array){ it doesn't work as you expect
Use forEach function or plan for loop
Also you have some error in sum function
See working example below:
function range(arr) {
var array = [];
var lower = Math.min(arr[0], arr[1]);
var upper = Math.max(arr[0], arr[1]);
for (var i = lower; i <= upper; i++) {
array.push(i);
}
return array;
}
function sum(array) {
var total = 0;
for (var i = 0; i < array.length; i++) {
total = total + array[i];
}
return total;
}
document.write('range ' + range([1, 10]) + '<br>');
document.write('sum ' + sum(range([1, 10])));
You need to modify sum & range function
function range (){
var array = [];
var lower = Math.min.apply(null, arguments);
var upper = Math.max.apply(null, arguments);
for (var i=lower;i<=upper;i++){
array.push(i);
}
return array;
}
function sum(array){
return array.reduce((x,y)=>x+y,0);
}
console.log(range(1, 10));
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(range(5, 2, -1)); //if we are considering min & max from params
// [-1, 0, 1, 2, 3, 4, 5]
console.log(sum(range(1, 10)));
// 55
Hello Dear check it now.
var array = [];
function range(arr, arr1) {
var lower = Math.min(arr);
var upper = Math.max(arr1);
for (var i = lower; i <= upper; i++) {
array.push(i);
}
}
function sum() {
var total = 0;
for (var i = 0; i < array.length; i++) {
total = total + array[i];
}
return total;
}
console.log(sum(range(1, 10)));
This is the correct answer to the problem at the end of the data structures chapter within Eloquent JavaScript
function range(start, end, step) {
let arr = []; //declare an empty array
var step = step || 1;//tests to see if step was supplied, otherwise it's 1
if(start < end)
{
for(let i = start; i <= end; i += step)
{
arr.push(i);
}
}
else
{
for(let i = start; i >= end; i += step)
{
arr.push(i);
}
}
return arr;
}
function sum(array) {
let total = 0;
for(let i = 0; i < array.length; i++)
{
total += array[i];
}
return total;
}
console.log(range(1, 10));
// → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(range(5, 2, -1));
// → [5, 4, 3, 2]
console.log(sum(range(1,10)));
// → 55
This solution takes into account of entering a step that isn't expected to be positive/negative, i.e range from 1 to 5, we would expect step to be positive, but if the user somehow entered a negative step then an empty array would occur.
The browser actually hangs for the opposite, if the array is expected to decrease, but the step sizes are > 0.
'use strict';
function range(start, end, step = 1){
let output = [];
if (start > end){
// Sanity check, all steps if expected to go down should be negative
if (step > 0){
step = -step;
}
for (;start >= end; start += step){
console.log(start);
output.push(start);
}
}
else{
// Likewise, as all steps should be positive
if (step < 0){
step = -step;
}
for (;start <= end; start += step){
output.push(start);
}
}
return output;
}
function sum(arr){
let output = 0;
for (let i of arr){
output += i;
}
return output;
}
console.log(range(1, 5, 1));
// → [1, 2, 3, 4, 5]
console.log(range(5, 1, -1));
// → [5, 4, 3, 2, 1]
// Notice this one step is a positive, but this is handled (original solution returned empty array)
console.log(range(5, 1, 1));
// → [5, 4, 3, 2, 1]
console.log(sum(range(1,10)));
// → 55
An improvement onto this is to use the reduce function for an array to sum instead of a for loop, i.e:
function sum(array){
return array.reduce((x,y)=>x+y,0);
}
For people finding this later on as I did, here is a way to write the range function so you can pass the input as written in the original question:
console.log(sum(range(1, 10)));
…and a cleaned up sum function similar to the one in A. Sharma's answer:
function range(lower, upper) {
let array = []
for (let i = lower; i <= upper; i++) {
array.push(i);
}
return array;
}
function sum(array) {
let total = 0;
for (let i in array) {
total = total + array[i];
}
return total;
}
console.log(sum(range(1, 10)));
Also worth mentioning:
The use of reduce in JagsSparrow's answer, which is elegant, while not entirely obvious and newcomer friendly as Mathias Vonende pointed out.
Negative step tolerant versions in answers from Jimmy Wei and user3225968.
This is the best solution I've got
function range(x,y){
var arr = [];
for(x;x<=y;x++){
arr.push(x);
};
return arr;
};
function sum(array){
return array.reduce((a,b) => a + b, 0);
};
console.log(sum(range(1,10)));
This answer is quite late but I am learning these things now and want to share my solution. I have not seen this solution provided for the specific question "Sum of a range in Javascript" so I wanted to share it. What I have done here is made use of the pop method for the array which allowed me not to specifically pass an array argument to the range function but to provide a solution to the argument in the way it was originally presented in the question.
var result = [];
var counter = 0;
function range(start, end) {
for (let i = start; i <= end; i++) {
result.push(i);
}
return result;
}
function sum(array) {
for (let i = 0; i < result.length; i++) {
counter += result.pop(i);
}
return counter;
}
console.log(range(1, 10));
// → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(sum(range(1, 10)));
// → 55
This can be accomplished very easily and efficiently without any globally scoped vars.
It's not clear in the original question what behavior should be applied to the -1 argument. It seems to be an indicator to reverse the range. In the below example, I've used a boolean to check this argument. A value of -1 would actually be the same as not providing a third argument. To reverse the range, pass in any truthy value.
function range(from, to, reverse) {
// Make sure our inputs are actually numbers
if (Number(from) != from || Number(to) != to) {
throw new TypeError("range() expects a Number as both it's first and second argument");
}
let o = []; // initialize our output array
// get the lowest value argument as our starting index
let i = Math.min(from, to);
// get the highest value argument as our ending index
let x = Math.max(from, to);
// push i onto our output array and then increment until i == x
while (i <= x) { o.push(i); i++; }
// reverse the range order if necessary
if (reverse) { o = o.reverse(); }
// return our output array
return o;
}
Then we can use Array.reduce to iterate through the range array and add each value (b) to the one before it (a) with the addition assignment operator (+=).
function sum(range) {
if (!(range instanceof Array)) {
throw new TypeError("sum() expects an Array as it's only argument");
} return range.reduce((a,b) => a+=b);
}
Testing it:
let a = range(1,10);
let b = range(5,2);
let c = range(5,2,true);
let d = range(3,-1);
let e = range(10,10);
console.log(a); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
console.log(b); // [ 2, 3, 4, 5 ]
console.log(c); // [ 5, 4, 3, 2 ]
console.log(d); // [ -1, 0, 1, 2, 3 ]
console.log(e); // [ 10 ]
console.log(range('test', 10)); // TypeError
console.log(range(1, 'test')); // TypeError
console.log(sum(a)); // 55
console.log(sum(b)); // 14
console.log(sum(c)); // 14
console.log(sum(d)); // 5
console.log(sum(e)); // 10
console.log(sum('test')); // TypeError
here my answer, I'd glad if you give me feedback about this solution.
let arr = [];
function range(x, y) {
for (let i = x; i <= y; i++) {
arr.push(i);
}
return arr;
}
function sum(array) {
const many = array.reduce((total, number) => {
return total + number;
}, 0);
return many;
}
console.log(sum(range(1, 10)));

Categories

Resources