Codewars Challenge

Hello everyone! I am practicing loops here and am doing this coding challenge on codewars. Training on Count of positives / sum of negatives | Codewars
Please note that I am not looking for the answer. I am only looking for WHY my code is incorrect. Please copy and paste this code into the codewars challenge link above and you will notice that when clicking “test” the code works; however, when clicking “submit”, the code does NOT work. (: Any help or advice on this would be appreciated. I feel like I am sooooooooooo close to solving the challenge :smiley:


  
  const arrayOfPositives = [];
  const arrayOfNegatives = [];
  for (let i = 0; i < input.length; i++) {
    if (input[i] === null || input[i] === 0) {
      continue;
    } else if (input[i] < 0) {
      arrayOfNegatives.push(input[i]);
    } else {
      arrayOfPositives.push(input[i]);
    };
  };
  
  const lengthOfPositives = arrayOfPositives.length;
  let sum = 0; 
  for (let i = 0; i < arrayOfNegatives.length; i++) {
    sum += arrayOfNegatives[i];
  }
  const newArray = []
  newArray.push(lengthOfPositives)
  newArray.push(sum)
  return newArray
}

I suspect at least part of your problem is that dynamic array allocation like this is slow. You don’t need those intermediate arrays.

This seems suspect to me. The instructions say:

“If the input is an empty array or is null, return an empty array.”

So if the value being passed into the function is null then there would be no input[i] and you would throw an error.

Actually, I guess the error would come at input.length in the for statement.

And in fact, when I try to submit your code I see the following error:

“TypeError: Cannot read property ‘length’ of null
at countPositivesSumNegatives (test.js:5:29)
at Context. (test.js:48:18)
at processImmediate (internal/timers.js:464:21)”

Hello there! Thanks so much for your response. I also did see that and I looked up the error message; however, I didn’t see how changing the .length would change anything because when I remove input.length from the for statement, the tests don’t work at all. Notice how the code I have now works whenever I use the “test” option, but it does NOT work whenever I click “submit”. Lol I feel like I am sooooooooo close to solving the problem hahaha.

It is probably because one or more of the tests passes null or an empty array as the argument to the function when you click the ATTEMPT button. The TEST button only calls the function twice and neither of those test cases pass a null or empty array as an argument. That is why your code passes the two test cases but not all the other cases when the ATTEMPT button is clicked.

If you want the TEST button to test for these two cases, you can add the following below the line that shows describe("Example tests", () => {

  it("Testing for when null value passed as argument", () => {
    let testData = null;
    let actual = countPositivesSumNegatives(testData);
    let expected = [];    
    assert.deepEqual(actual, expected);
  });
  
  it("Testing for when an empty array passed as argument", () => {
    let testData = [];
    let actual = countPositivesSumNegatives(testData);
    let expected = [];    
    assert.deepEqual(actual, expected);
  });  
1 Like

Here is my code below. The error message is

TypeError: Cannot read property 'length' of null
    at countPositivesSumNegatives (test.js:7:29)
    at Context.<anonymous> (test.js:51:18)
    at processImmediate (internal/timers.js:464:21)

and

expected [ 0, 0 ] to deeply equal []

  
  const arrayOfPositives = [];
  const arrayOfNegatives = [];
  for (let i = 0; i < input.length; i++) {
    if (input[i] === null || input[i] === 0) {
      continue;
    } else if (input[i] < 0) {
      arrayOfNegatives.push(input[i]);
    } else {
      arrayOfPositives.push(input[i]);
    };
  };
  
  const lengthOfPositives = arrayOfPositives.length;
  let sum = 0; 
  for (let i = 0; i < arrayOfNegatives.length; i++) {
    sum += arrayOfNegatives[i];
  }
  const newArray = []
  newArray.push(lengthOfPositives)
  newArray.push(sum)
  return newArray
}

You have not changed any code since receiving good advice from three other users here.

First, try to fix your code to properly handle the cases where null or and empty array is passed to the function. Once those two cases are resolved, you will almost have a working solution.

Oh whoops sorry! pasted the wrong one!


  
  const arrayOfPositives = [];
  const arrayOfNegatives = [];
  for (let i = 0; i < input.length; i++) {
    if (input[i] === null || input[i] === 0 || input[i] === []) {
      return [];
    } else if (input[i] < 0) {
      arrayOfNegatives.push(input[i]);
    } else {
      arrayOfPositives.push(input[i]);
    };
  };
  
  const lengthOfPositives = arrayOfPositives.length;
  let sum = 0; 
  for (let i = 0; i < arrayOfNegatives.length; i++) {
    sum += arrayOfNegatives[i];
  }
  const newArray = []
  newArray.push(lengthOfPositives)
  newArray.push(sum)
  return newArray
}

You are still not understanding the advice being given. If you call the function as:

countPositivesSumNegatives(null);

the for loop will error out because input is not an array, so it will not have a length property.

The logic you have written in the following if statement does not help you at all if input is null or is an empty array:

if (input[i] === null || input[i] === 0 || input[i] === []) {

The first line of the Instructions states:

Given an array of integers.

This means that a non-empty array will only have integers and will not have null or empty arrays as elements of the array.

Yes, I know the input.length was mentioned, but I guess I missed what needed to be done to fix it. My apologies. The reason I did input is because when I logged input to the console, it came up with an array.

So I guess I have to declare an empty array and return that empty array variable, no?

In the 2 test cases, that is true.

In other cases when clicking the ATTEMPT button, that is definitely not true, so you have to write code that handles the two cases the last line in the Instructions mentions (see below):

If the input is an empty array or is null, return an empty array.

You do not have to declare an empty array to return an empty array. You just return an empty array.

And I thought the logic read this way:
if input at index is null, 0, or an empty array
return empty array

if (input[i] === null || input[i] === 0 || input[i] === []) {

and if i remove the .length, i get

expected [ 0, 0 ] to deeply equal [ 10, -65 ]

Not quite. The if statement checks if the value of the element located at index i of input array is equal to null or the value of the element located at index i of input array is equal to 0 or the value of the element located at index i is equal to a specific array (that happens to be empty), then return an empty array.

This is completely different logic than checking if the value of input is null or the length of input is equal to 0 (one way of checking if an array is empty).

The bottom line is you are confusing input with an element of input, assuming input is an array at all.

I’m checking here How to Check if a JavaScript Array is Empty or Not with .length. and it states that this is one way of checking if an array is empty.

For example, at some point in the test of submitting the challenge, it will have the input as an empty array, so if you did input.length, it would be 0, right? Because during that specific test where (for example) const input = [], doing input.length will be 0, correct?

That is what I mentioned in my last reply (see 2nd to last sentence.).

yeah I know. I was just looking up what you typed so I made sure I understood that you were saying that I need to have somewhere in my logic that I have to check for that. Well, I guess there’s something I’m just not understanding lol. Still kinda lost. Thanks for bearing with me. my apologies lol

If input is null, then input.length is not defined. You cannot call input.length when null is passed into your function.