FAQ: Code Challenges: JavaScript Fundamentals - finalGrade()

It’s a logical progression (process of elimination). Study it closely to see what I mean by that.

1 Like

Hi guys, my code is working but I’m thinking of how to reduce it! Especially this part: grade1 < 100 && grade2 > 0 && grade2 < 100 && grade3 > 0 && grade3 < 100
Is it possible to define it first so it doesn’t need to be repeated?

Thanks for the help!

const finalGrade = (grade1, grade2, grade3) => {

const average = ((grade1 + grade2 + grade3) / 3);

if (average >= 0 && average <= 59 && grade1 > 0 && grade1 < 100 && grade2 > 0 && grade2 < 100 && grade3 > 0 && grade3 < 100) {
return ‘F’;

} else if (average >= 60 && average <= 69 && grade1 > 0 && grade1 < 100 && grade2 > 0 && grade2 < 100 && grade3 > 0 && grade3 < 100) {
return ‘D’;

} else if (average >= 70 && average <=79 && grade1 > 0 && grade1 < 100 && grade2 > 0 && grade2 < 100 && grade3 > 0 && grade3 < 100) {
return ‘C’;

} else if (average >=80 && average <= 89 && grade1 > 0 && grade1 < 100 && grade2 > 0 && grade2 < 100 && grade3 > 0 && grade3 < 100) {
return ‘B’;

} else if (average >= 90 && average <=100 && grade1 > 0 && grade1 < 100 && grade2 > 0 && grade2 < 100 && grade3 > 0 && grade3 < 100) {
return ‘A’;
} else
{
return ‘You have entered an invalid grade.’;
}
}

Validate first, then compute the average, then assign a letter grade. Since there are three values that must be validated, it will take some logic.

if (grade1 < 0 || grade1 > 100 || grade2 < 0 ...) {
    return "You have ..."
}
// compute average
//  assign letter grade and return
1 Like

function finalGrade(test1,test2,test3){

var final = test3;

var mid = test2;

var first = test1;

var average = (first + mid + final)/3;

var raverage = Math.round(average);

if((final < 0 || final > 100) || (first < 0||

first > 100) || (mid < 0 || mid > 100)){

return 'You have entered an invaild grade.';

}else if(raverage <= 59){

return ‘F’;

}else if(raverage > 60 && raverage <= 69){

return ‘D’;

}else if(raverage > 70 && raverage <= 79){

return ‘C’;

}else if(raverage > 80 && raverage <= 89){

return ‘B’;

}else if(raverage >= 90 && raverage == 100){

return ‘A’;

}

};

I keep getting invalid, what am I doing wrong?

Should it be necessary to round? That seems like arbitrary code, if you ask me.

Consider where the average is computed… Before the validation. What effect will any invalid grades have on the average computed, above? Answer: it will skew the value and be technically worthless. Bottom line, do the validation first, and don’t round. It is not important that we use integers. Grades can be floats.

As often gets asked, what happens when the grade is higher than 69 but lower than 70? Same question all the way up the line.

How can a grade be equal to 100 just because it is greater than 90?

1 Like

Ok yeah that makes sense, thank you

1 Like

function finalGrade(test1,test2,test3){

var final = test3;

var midterm = test2;

var homework = test1;

var average = (homework + midterm + final)/3;

if(average <= 59){

return ‘F’;

}else if(average > 60 && average <= 69){

return ‘D’;

}else if(average > 70 && average <= 79){

return ‘C’;

}else if(average > 80 && average <= 89){

return ‘B’;

}else if(average >= 90 && average <= 100){

return ‘A’;

} else if((mid < 0 || midterm > 100) || (midterm < 0 || final > 100) || (homework < 0 || homework > 100)){

return 'You have entered an invaild grade.';

}

};

OK what’s going on?

I keep getting this Incorrect:If any of the grades passed in are less than 0 or greater than 100, the function should return ‘You have entered an invalid grade.1’

and I been check thing form and I can’t see what I am doing wrong

That line will likely only ever come up in the results if an input is greater 100. Does it make sense to validate the inputs after all the code has run its course, rather than before the average is computed?.

Ok thank I think I understand Just need to brake it down a test it.

1 Like

Hi, I’ve written code which works but doesn’t satisfy the checker. What am I doing wrong?

// Write your function here:

const finalGrade = (num1, num2, num3) => {

if ((num1 || num2 || num3) < 0 || (num1 || num2 || num3) > 100) {

return 'You have entered an invalid grade.';

}

else {

let average = (num1 + num2 + num3) / 3;

if (average <= 59) {

  return "F";

}

else if (average <= 69) {

  return "D";

} 

else if (average <= 79) {

  return "C";

} 

else if (average <= 89) {

  return "B";

} 

else if (average <= 100) {

  return "A";

} 

}

}

// Uncomment the line below when you’re ready to try out your function

console.log(finalGrade(99, 92, 95)) // Should print ‘A’

// We encourage you to add more function calls of your own to test your code!

First off, we like that you placed the validation at the top of your function. That’s one thing right, for sure. The rest looks okay, and can even handle floats, so that’s even better.

One suspects the problem is with the stray closing brace at the very end.

Aside

Since values outside of the valid range are already excluded, the final else if could be just an else (a default case) as the only letter left to return is ‘A’.

Furthermore, considering return is employed in every branch, we don’t even need the else if, just if, and the last return can be on its only line.

if (..) return 'F';
if (..) return 'D';
...
return 'A'

Mind, that is only if the checker is only looking at what is returned, not how the function is coded.

The only thing nobody checks for is validation if it is a number that has been put in by the user.
After some research I found the folowing solution:

// Write your function here
function finalGrade(numberOne, numberTwo, numberThree) {
  if  (numberOne < 0 || numberOne >100 || numberTwo < 0 || numberTwo > 100 || numberThree < 0 || numberThree > 100) {
    return 'You have entered an invalid grade.'
  }
  if (isNaN(numberOne) === true || isNaN(numberTwo) === true || isNaN(numberThree) === true) {
    return 'You should enter a number, not some plain text!';
  }
 
  let averageGrade = (numberOne + numberTwo + numberThree) / 3;
  
Rest of the code....

console.log(finalGrade('bah',75,100))

output: You should enter a number, not some plain text!

Link to solution for more explanation: isNaN / is Not a Number explained

How can I make this work?

I want to use the for loop in this to grab the value of each argument and check if it matches the condition, but it doesn’t seem to work. Any insights into how to make this work will be much appreciated.

const finalGrade = (g1, g2, g3) => {
  let grades = [g1, g2, g3];

  let i;

  for (i = 0; grades.length <= 3; i++) {
    if (grades[i] < 0  || grades[i] > 100) {
      return 'You have entered an invalid grade.';
    }
  }
  
  let average = Math.floor((g1 + g2 + g3)/3);
  if (average <= 59) {
    return 'F';
  } else if (average <= 69) {
    return 'D';
  } else if (average <= 79) {
    return 'C';
  } else if (average <= 89) {
    return 'B';
  } else if (average <= 100) {
    return 'A';
  } 
};

console.log(finalGrade(-90, 50, 120));

Take another look at how your using your for loop here:

(i = 0; grades.length <= 3; i++)

A for loop is in a way related to the while in the fact that they both have a statement which is condition that must be true in order for the loop to iterate again. In a for loop the second condition is the one that must evaluate to true in order to keep running, but it is also the one that must at some point evaluate to false in order to terminate the loop.
Currently your second condition is grades.length <= 3. Your not modifying the array at any point in the loop so this will never evaluate to false given the array starts with a length of 3, and under most circumstances you have an infinite loop.
The only reason your program terminates is because once i gets to be more than the length of the array you are going through undefined values, and undefined is neither less than 0 or more than 100.

2 Likes

Thank you so much for your feedback 8-bit-gaming! You are right that I didn’t have any way to stop the loop because grades.length was always true, taking that information, I tweaked the code so it will stop the loop and still have the whole function work if all the grades are propper.

const finalGrade = (g1, g2, g3) => {
  let grades = [g1, g2, g3];
  let gradeLength = grades.length; // This variable allows me to change it to undefined so the for loop stops.
  let i;

  for (i = 0; gradeLength <= 3; i++) {
    
    if (grades[i] < 0  || grades[i] > 100) {
      return 'You have entered an invalid grade.'; // if this statement returns true, the whole function stops.
    } else {
      if (i == 2) { // when it loops 3 times which is (0, 1, 2) it will stop the loop if the condition above is false for all of the array.
        gradeLength = undefined; // when this is runned, the function will still process because return is not being used.
      }
    }
    
  }
  
  let average = Math.floor((g1 + g2 + g3)/3);
  if (average <= 59) {
    return 'F';
  } else if (average <= 69) {
    return 'D';
  } else if (average <= 79) {
    return 'C';
  } else if (average <= 89) {
    return 'B';
  } else if (average <= 100) {
    return 'A';
  } 
};

console.log(finalGrade(20, 180, -15));
1 Like

This code certainly works, and I compliment you on your ingenuity, but you may be unnecessarily complicating things here. Your for loop is already working on the variable i every time it iterates, and currently you are using i indirectly to tell it when to stop through the value of gradeLength.
Instead you could skip the middle man variable and terminate your loop based entirely on i:

for (let i = 0; i < grades.length; i++) {
  // code here
}

Now you have no need of another variable nor extra if blocks.

1 Like

Oh, that’s much better, Thank you again, :grinning:

1 Like