JavaScript end of loop NaN for a numerical addition - javascript

when I run this program I end up with NaN at the end; I'd appreciate some form of explanation, as I'm stumped! I have an odd feeling it has to do something with scope...
https://jsfiddle.net/Smuggles/evj46a23/
var array = []
var range = function(start, end) {
for (var count = start; count <= end; count++) {
array.push(start);
start += 1;
}
console.log(array);
}
var sum = function() {
var result = 0
var arrayLength = array.length
for (var count = 0; count <= arrayLength; count++) {
result += array[count]
console.log(result);
}
}
console.log(sum(range(1, 10)));

2 things:
You need to change the for loop in the sum function to be < arrayLength and not <= arrayLength. You are dealing with array lengths which start with a 0 index.
You need to return the result from the sum function
var array = [];
var range = function(start, end) {
for (var count = start; count <= end; count++) {
array.push(start);
start += 1;
}
};
var sum = function() {
var result = 0;
var arrayLength = array.length;
for (var count = 0; count < arrayLength; count++) {
result += array[count];
}
return result;
};
console.log(sum(range(1, 10)));
Given an array of [4,5,6], the indexes would be as follows:
0: 4
1: 5
2: 6
Therefore, when you use the length property of the array (3), you are referencing an index that does not exist, which returns undefined. It tries to do the math on the undefined, which causes a NaN. This is why you have to use < arrayLength.
The functional approach:
It would help to make those functions a bit more "pure". Instead of maintaining state outside of the functions (with var array = []), just return the values from the functions: See the following for example:
function range(start, end) {
var arr = [];
for (var i = start; i <= end; i++) {
arr.push(i);
}
return arr;
}
function sumArray(array) {
return array.reduce(function(a, b) {
return a + b;
});
}
console.log(sumArray(range(1, 10)));
Each function takes arguments, and simply returns the result. This way, you approach this a little more "functional".

Description in Comments of Code
var array = [];
var range = function(start, end) {
//simplified the loop to remove unnecessary variables
for (; start <= end; start++) {
array.push(start);
}
return array;
}
var sum = function() {
var result = 0;
// move length to scope of the loop
// change to < rather than <= due to zero index nature of arrays
for (var count = 0, length = array.length; count < length; count++) {
result += array[count];
}
// return the result from the function
return result;
}
// gets an array from 1-10
var arr = range(1, 10);
// print the array to the console
console.log(arr);
// print the sum to the console
console.log(sum(arr));

Related

Write a function which returns the sum of the values for each parameter it receives

I want the result to be the sum of every number, but instead, it only sums the first number with the rest. For example if the parameter were : 1,2,3,4,5
it should come out with 15 but instead, it became 3456. Where did i go wrong?
Thank u guys, i m new to this and thing were really complicated :((
function func1(sum) {
var result = '';
var i;
for (i = 1; i < arguments.length; i++) {
result += arguments[i] + sum;
}
return result;
}
Start with result being a number, not a string: var result = 0.
If you're iterating through arguments, you may as well skip the named first argument altogether.
Start iterating from 0, not 1.
function func1() {
var result = 0;
var i;
for (i = 0; i < arguments.length; i++) {
result += arguments[i];
}
return result;
}
console.log(func1(1, 2, 3, 4, 5));
This should work
function sum(value) {
let result = 0;
for(let i =0; i < value.length; i++) {
result +=value[i];
}
return result
}
let arry = [1,2,3,4,5]
console.log(sum(arry)) //15

Faster Algorithm for JavaScript function call within a function

I have written a function and called another function inside but my tests show that it is not time optimized. How can I make the following code faster?
function maxSum(arr, range) {
function sumAll(array1, myrange) {
var total = 0;
if (Array.isArray(myrange)) {
for (var i = myrange[0]; i <= myrange[1]; i++) {
total += array1[i];
}
return total;
} else return array1[myrange];
}
var mylist = [];
var l = range.length;
for (var n = 0; n < l; n++) {
mylist.push(sumAll(arr, range[n]));
}
return Math.max.apply(null, mylist);
}
Algorithmic optimization: create new array with cumulative sums from index 0 to every index
cumsum[0] = 0;
for (var i = 1; i <= arr.Length; i++) {
cumsum[i] = cumsum[i-1] + arr[i-1]
Now you don't need to calculate sums for every range - just get difference
sum for range (i..j) = cumsum[j+1] - cumsum[i];
in your terms:
function sumAll(array1, myrange) {
return cumsum[myrange[1]+1] - cumsum[myrange[0]];
}
example:
arr = [1,2,3,4]
cumsum = [0,1,3,6,10]
sum for range 1..2 = 6 - 1 = 5
P.S. If your array might be updated, consider Fenwick tree data structure
1) You can define the function sumAll outside of the function maxSum because every time you call maxSum the javascript engine is recreating a fresh new function sumAll.
2) You can define myrange[1] as a variable in the initialiser part to avoid javascript to look for myrange[1] at each iteration.
for (var i = myrange[0]; i <= myrange[1]; i++) {
total += array1[i];
}
become this:
for (var i = myrange[0], len = myrange[1]; i <= len; i++) {
total += array1[i];
}
Full working code based on #MBo's excellent optimization. This passes all the tests at https://www.codewars.com/kata/the-maximum-sum-value-of-ranges-challenge-version/train/javascript, which I gather is where this problem comes from.
function maxSum(arr, ranges) {
var max = null;
var sums = [];
var sofar = 0;
for (var i = 0; i <= arr.length; i++) {
sums[i] = sofar;
sofar += arr[i];
}
for (var i = 0; i < ranges.length; i++) {
var sum = sums[ranges[i][1]+1] - sums[ranges[i][0]];
if (max === null || sum > max) {
max = sum;
}
}
return max;
}

Getting the average returns NAN - JS

I am writing a function called "computeAverageOfNumbers".
Given an array of numbers, "computeAverageOfNumbers" returns their average.
Notes:
If given an empty array, it should return 0.
Here's my code:
function computeAverageOfNumbers(nums) {
var total = 0;
for (var i = 0; i < nums.length; i++) {
total += nums[i];
}
var avg = total / nums.length;
return avg;
}
var input = [];
var output = computeAverageOfNumbers(input);
console.log(output); // --> returns NaN instead of 0
As you can see my code returns NaN when you submit an empty array but works if you put regular array items like var input = [1,2,3,4,5];
If given an empty array, it should return 0.
Am I missing something?
Just do below
if( nums.length == 0 ) return 0;
in code
function computeAverageOfNumbers(nums) {
if (nums.length == 0) return 0;
var total = 0;
for (var i = 0; i < nums.length; i++){
total += nums[i];
}
var avg = total / nums.length;
return avg;
}
Just check if nums.length
function computeAverageOfNumbers(nums) {
if (nums.length === 0) {
return 0
} else {
var total = 0;
for (var i = 0; i < nums.length; i++) {
total += nums[i];
}
var avg = total / nums.length;
return avg;
}
}
var input = [];
var output = computeAverageOfNumbers(input);
console.log(output);
input = [2,5,9,13];
output = computeAverageOfNumbers(input);
console.log(output);
When your array is empty, nums.length = 0 and a if you divide a number by 0, it gives you NaN.
Just change
var avg = total / nums.length;
to
var avg = (nums.length)?total/nums.length:0
to solve your trouble
When you pass an empty array then this line:
var avg = total / nums.length;
Is a division by zero, so avg will be NaN. I would short circuit the function at the start with:
if (nums.length === 0)
return 0;
Bear in mind ideally you also want to do some type checking to confirm you've got an array, etc. but the above should give you the basics.

How to programmatically create 3D array that increments to a defined number, resets to zero, and increments again?

Starting with this initial 2D array:
var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]];
I need to create this 3D array programmatically:
var fullArray = [
[[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]],
[[3,4],[0,1],[5,6],[2,3],[6,7],[3,4]],
[[4,5],[1,2],[6,7],[3,4],[0,1],[4,5]],
[[5,6],[2,3],[0,1],[4,5],[1,2],[5,6]],
[[6,7],[3,4],[1,2],[5,6],[2,3],[6,7]],
[[0,1],[4,5],[2,3],[6,7],[3,4],[0,1]],
[[1,2],[5,6],[3,4],[0,1],[4,5],[1,2]],
[[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]],
[[3,4],[0,1],[5,6],[2,3],[6,7],[3,4]],
[[4,5],[1,2],[6,7],[3,4],[0,1],[4,5]],
[[5,6],[2,3],[0,1],[4,5],[1,2],[5,6]]
];
See the pattern?
On each pair, the [0] position should increment to 6 (from any starting number <= 6) and then reset to 0 and then continue incrementing. Similarly, the [1] position should increment to 7 (from any starting number <= 7) and then reset to 1 and then continue incrementing.
In this example, there are 10 2D arrays contained in the fullArray. However, I need this number to be a variable. Something like this:
var numberOf2DArraysInFullArray = 12;
Furthermore, the initial array should be flexible so that initialArray values can be rearranged like this (but with the same iteration follow-through rules stated above):
var initialArray = [[6,7],[2,3],[5,6],[4,5],[1,2],[6,7]];
Any thoughts on how to programmatically create this structure?
Stumped on how to gracefully pull this off.
Feedback greatly appreciated!
Here's a solution, I've separated the methods, and I made it so if instead of pairs it's an N size array and you want the [2] to increase up to 8 and reset to 2, if that's not needed you can simplify the of the loop for(var j = 0; j < innerArray.length; j++)
var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]];
var create3DArray = function(array, size){
var newArray = [initialArray];
for(var i = 0; i < size; i++)
{
newArray.push(getNextArrayRow(newArray[i]));
}
return newArray;
}
var getNextArrayRow = function(array){
var nextRow = [];
for(var i = 0; i < array.length; i++)
{
var innerArray = array[i];
var nextElement = [];
for(var j = 0; j < innerArray.length; j++)
{
var value = (innerArray[j] + 1) % (7 + j);
value = value === 0 ? j : value;
nextElement.push(value);
}
nextRow.push(nextElement);
}
return nextRow;
}
console.log(create3DArray(initialArray,3));
Note, the results from running the snippet are a bit difficult to read...
var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]];
var numOfArrays = 10;
// get a range array [0, 1, 2, ...]
var range = [];
for (var i = 0; i < numOfArrays; i++) {
range.push(i);
}
var result = range.reduce(function(prev, index) {
if (index == 0) {
return prev;
}
prev.push(transformArray(prev[index - 1]));
return prev;
}, [initialArray])
console.log(result);
function transformArray(arr) {
return arr.map(transformSubArray)
}
function transformSubArray(arr) {
return arr.map(function(val) {
return val == 7 ? 0 : val + 1;
})
}
Here's a pretty simple functional-ish implementation

JavaScript Permutations

I am trying to count the number of permutations that do not contain consecutive letters. My code passes tests like 'aabb' (answer:8) and 'aab' (answer:2), but does not pass cases like 'abcdefa'(my answer: 2520; correct answer: 3600). Here's my code:
function permAlone(str) {
var totalPerm = 1;
var result = [];
//assign the first letter
for (var i = 0; i < str.length; i++) {
var firstNum = str[i];
var perm = firstNum;
//create an array from the remaining letters in the string
for (var k = 0; k < str.length; k++) {
if (k !== i) {
perm += str[k];
}
}
//Permutations: get the last letter and change its position by -1;
//Keep changing that letters's position by -1 until its index is 1;
//Then, take the last letter again and do the same thing;
//Keep doing the same thing until the total num of permutations of the number of items in the string -1 is reached (factorial of the number of items in the string -1 because we already established what the very first letter must be).
var permArr = perm.split("");
var j = permArr.length - 1;
var patternsLeft = totalNumPatterns(perm.length - 1);
while (patternsLeft > 0) {
var to = j - 1;
var subRes = permArr.move(j, to);
console.log(subRes);
if (noDoubleLettersPresent(subRes)) {
result.push([subRes]);
}
j -= 1;
if (j == 1) {
j = perm.length - 1;
}
patternsLeft--;
}
}
return result.length;
}
Array.prototype.move = function(from, to) {
this.splice(to, 0, (this.splice(from, 1))[0]);
return this.join("");
};
function totalNumPatterns(numOfRotatingItems) {
var iter = 1;
for (var q = numOfRotatingItems; q > 1; q--) {
iter *= q;
}
return iter;
}
function noDoubleLettersPresent(str) {
if (str.match(/(.)\1/g)) {
return false;
} else {
return true;
}
}
permAlone('abcdefa');
I think the problem was your permutation algorithm; where did you get that from? I tried it with a different one (after Filip Nguyen, adapted from his answer to this question) and it returns 3600 as expected.
function permAlone(str) {
var result = 0;
var fact = [1];
for (var i = 1; i <= str.length; i++) {
fact[i] = i * fact[i - 1];
}
for (var i = 0; i < fact[str.length]; i++) {
var perm = "";
var temp = str;
var code = i;
for (var pos = str.length; pos > 0; pos--) {
var sel = code / fact[pos - 1];
perm += temp.charAt(sel);
code = code % fact[pos - 1];
temp = temp.substring(0, sel) + temp.substring(sel + 1);
}
console.log(perm);
if (! perm.match(/(.)\1/g)) result++;
}
return result;
}
alert(permAlone('abcdefa'));
UPDATE: In response to a related question, I wrote an algorithm which doesn't just brute force all the permutations and then skips the ones with adjacent doubles, but uses a logical way to only generate the correct permutations. It's explained here: Permutations excluding repeated characters and expanded to include any number of repeats per character here: Generate all permutations of a list without adjacent equal elements
I agree with m69, the bug seems to be in how you are generating permutations. I got 3600 for 'abcdefa' by implementing a different algorithm for generating permutations. My solution is below. Since it uses recursion to generate the permutations the solution is not fast, however you may find the code easier to follow, if speed is not important.
The reason for having a separate function to generate the array index values in the permutations was to verify that the permutation code was working properly. Since there are duplicate values in the input strings it's harder to debug issues in the permutation algorithm.
// Simple helper function to compute all permutations of string indices
function permute_indices_helper(input) {
var result = [];
if (input.length == 0) {
return [[]];
}
for(var i = 0; i < input.length; i++) {
var head = input.splice(i, 1)[0];
var tails = permute_indices_helper(input);
for (var j = 0; j < tails.length; j++) {
tails[j].splice(0, 0, head);
result.push(tails[j]);
}
input.splice(i, 0, head); // check
}
return result;
};
// Given an array length, generate all permutations of possible indices
// for array of that length.
// Example: permute_indices(2) generates:
// [[0,1,2], [0,2,1], [1,0,2], ... , [2, 0, 1]]
function permute_indices(array_length) {
var result = [];
for (var i = 0; i < array_length; i++) {
result.push(i);
}
return permute_indices_helper(result);
}
// Rearrange letters of input string according to indices.
// Example: "car", [2, 1, 0]
// returns: "rac"
function rearrange_string(str, indices) {
var result = "";
for (var i = 0; i < indices.length; i++) {
var string_index = indices[i];
result += str[string_index];
}
return result;
}
function permAlone(str) {
var result = 0;
var permutation_indices = permute_indices(str.length);
for (var i = 0; i < permutation_indices.length; i++) {
var permuted_string = rearrange_string(str, permutation_indices[i]);
if (! permuted_string.match(/(.)\1/g)) result++;
}
return result;
}
You can see a working example on JSFiddle.

Categories

Resources