Grading Students in JS with recursion - Range Error - javascript

I was trying to work on this hackerrank problem.
Every student receives a grade in the inclusive range from
0-100 to .
Any less than 38 is a failing grade.
Sam is a professor at the university and likes to round each student's according to these rules:
If the difference between grade the and the next multiple of
5 is less than 3, round up to the next multiple of 5. If the value of grade is less than 38, no rounding occurs as the
result will still be a failing grade.
Given the initial value of for each of Sam's students, write code to
automate the rounding process.
My code is:
function gradingStudents(grades) {
const roundup = y => y + 1;
{
if ( grades < 38 || grades % 5 === 0) return grades;
else if ( grades % 5 < 4 && grades % 5 !== 0) return roundup(grades);
}
{
if (roundup % 5 === 0) return roundup;
else { gradingStudents(roundup + 1) }
}
}
gradingStudents(38) // -> 39
I tried to use Math.ceil(grades) inside the variable roundup but output didnt change. So, when you invoke the function with a number that is not before a multiple of 5 (e.g. 43) it returns the proceeding number. However, if it is the number before a multiple of 5 it gives a range error. "maximum call stack size reached."
As far as I got, the code doesnt proceed to the second part. Even if it did, I am not sure if it would fetch the current value of the function roundup when dealing with if statements in the second block.
What do I dont get in here?
Also, this is actually meant for an array output but since I am a beginner I am pretty much okay with this one for the start as well :D .

Javascript solution:
function gradingStudents(grades) {
return grades.map((grade) => {
if (grade > 37) {
const offset = 5 - (grade % 5);
if (offset < 3) {
grade += offset;
}
}
return grade;
});
}

Try this:
function gradingStudents(grades) { //input: 43
var finalGrade;
if(grade < 38)
return grades;
else{
var gradeDif = grades % 5; //3
if(gradeDif > 3){
return grades;
}
else {
return grades + (5 - gradeDif); //Output: 45
}
}
}

One solution calculates the next multiple of 5 no bigger than the grade and uses that value to test whether or not to round up (next5 - grade < 3).
We write a simple function to round an individual grade and then for a list of grades use .map with that function.
const roundGrade = (grade) => {
const next5 = 5 * Math.ceil (grade / 5)
return (grade < 38) ? grade : (next5 - grade < 3) ? next5 : grade
}
const gradingStudents = (grades) =>
grades .map (roundGrade)
console .log (gradingStudents ([73, 67, 38, 33]))
Note that, like most solutions to this problem, no recursion is needed.

1-Use the Array.prototypt.map according to the question logic.
const gradingStudents = (grades) => grades
.map(n => (n >= 38 && n % 5 >= 3)?(n + ( 5 - ( n % 5 ) )):n )
let result = gradingStudents([0,25,38,56,89,77,78,57,58])
console.log(result)

My solution is this
function gradingStudents(grades) {
grades.map((grade,i)=>{
if(grade >= 38){
let fg = (grade/5).toString().split('.');
if(fg[1]>5){
grades[i]=((parseInt(fg[0],10)+1) * 5);
};
}
});
return grades;
}
console.log(gradingStudents([73,67,38,33]));

my solution:
function gradingStudents(grades) {
return grades.map(function(grade) {
return (grade >= 38 && grade % 5 >= 3) ? grade + 5 - (grade % 5) : grade;
});
}

Related

JS: Grading System of a school Any Fix (Error== undefined) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 months ago.
Improve this question
A school has the following rules for the grading system:
// a. 45 to 50 - D
// b. 50 to 60 - C
// c. 60 to 80 - B
// d.Above 80 - A
Ask the user to enter marks, name as well as Roll No and print the corresponding grade
const school_grading_system = () => {
let student_details = {
name_of_student: prompt("Enter your name:"),
roll_number_of_student: Number(prompt("Enter your Roll No: ")),
marks_of_student: Number(prompt("Enter your marks out of 100: ")),
percentage_obtained_student: function() {
return ((this.marks_of_student / 100) * 100)
}
}
if (this.percentage_obtained_student >= 80 && this.percentage_obtained_student < 80) {
console.log(`${this.percentage_obtained_student}:Good Job! You have scored A Grade`)
} else if (this.percentage_obtained_student >= 60 && this.percentage_obtained_student < 60) {
console.log(`${this.percentage_obtained_student}: Good! You have obtained B Grade`)
} else if (this.percentage_obtained_student >= 50 && this.percentage_obtained_student < 60) {
console.log(`${this.percentage_obtained_student}: Good! You have obtained C Grade`)
} else if (this.percentage_obtained_student >= 45 && this.percentage_obtained_student < 50) {
console.log(`${this.percentage_obtained_student}: Good! You have obtained D Grade`)
}
}
console.log(school_grading_system())
// Rule 1: Kinda keep it simple
// As total marks are going to be 100 so no need for a percentage method
const school_grading_system = () => {
let student_details = {
name_of_student: prompt("Enter your name:"),
roll_number_of_student: Number(prompt("Enter your Roll No: ")),
marks_of_student: Number(prompt("Enter your marks out of 100: "))
}
if (student_details.marks_of_student >= 45 && student_details.marks_of_student < 50) {
return "Grade D"
} else if (student_details.marks_of_student >= 50 && student_details.marks_of_student < 60) {
return "Grade C"
} else if (student_details.marks_of_student >= 60 && student_details.marks_of_student < 80) {
return "Grade B"
} else if (student_details.marks_of_student >= 80 && student_details.marks_of_student <= 100) {
return "Grade A"
}
}
console.log(school_grading_system())
// Note: I have not displayed the name and marks stuff because I hope you are capable enough to do that so I am leaving that upon you
There are some problems within your code that lead to the result being wrong, let's break them down:
The use of this keyword in your school_grading_system (outside the student_details object) is the window object and NOT student_details object so when you try this.percentage_obtained_student that is translated to window.percentage_obtained_student and as window dosen't have an attribute called percentage_obtained_student the result of that call would be undefined that lead to deliver the wrong results. So instead of this.percentage_obtained_student you should use student_details.percentage_obtained_student to get the needed piece of data.
Another issue is the your conditions found on the if .. else statements. Let's imagine a student having 80 as his score, when you say student_details.percentage_obtained_student >= 80 && student_details.percentage_obtained_student < 80 this condition will never be satisfied because it negates itself as that conditon translates to IF the SCORE is greater than or equal to 80 AND the score is less than 80 but we cannot have a number bigger or equal and lower than itself at the same time (I couldn't describe more accurately).
With that being said, here's a corrected version of your code:
const school_grading_system = () => {
let student_details = {
name_of_student: prompt("Enter your name:"),
roll_number_of_student: Number(prompt("Enter your Roll No: ")),
marks_of_student: Number(prompt("Enter your marks out of 100: ")),
}
/** the conditons are now refined */
if (student_details.marks_of_student >= 80) {
console.log(`${student_details.marks_of_student}:Good Job! You have scored A Grade`)
} else if (student_details.marks_of_student >= 60) {
console.log(`${student_details.marks_of_student}: Good! You have obtained B Grade`)
} else if (student_details.marks_of_student >= 50) {
console.log(`${student_details.marks_of_student}: Good! You have obtained C Grade`)
} else if (student_details.marks_of_student >= 45) {
console.log(`${student_details.marks_of_student}: Good! You have obtained D Grade`)
}
}
school_grading_system();
By the way, you function has some unhandled cases, to mention some, it doesn't take into consideration the case of a score LESS THAN 45. Also, it doesn't handle wrong user inputs like when the user types a number higher than 100.
Here is a shorter way of doing the grading work:
// 45 to 50 - D
// 50 to 60 - C
// 60 to 80 - B
// Above 80 - A
const grades=[[101,"*** impossible - you must have cheated!"],[80,"A"],[60,"B"],[50,"C"],[45,"D"],[0,"E or below"]];
[95,23,57,-5,45,83,110,74,62].forEach(s=>
console.log(`your score of ${s} gets you the grade ${(grades.find(([g])=>s>=g)??[0,"below ZERO"])[1]}`))

Calling a function with array as an argument

pls I want this function to loop through any array and output a new array base on the logic written but am only getting the initial array when I call the function with the array as argument, pls I need help. Below is the code
const scores = [35, 68, 70, 38];
const scores1 = [89, 42, 33];
function gradingStudents(...grades) {
const newScores = grades.map(function (grade) {
if (grade + 2 >= 40 && grade % 5 >= 3) {
return grade % 5 == 3 ? grade + 2 : grade + 1;
} else if (grade + 2 >= 40 && grade % 5 < 3) {
return grade;
} else {
return grade;
}
});
return newScores;
}
console.log(gradingStudents(scores1));
Rest Paramanter syntax (...) is used when you are handling with dynamic number of arguments. Here you are passing only one argument to the function. Remove the ... from the function param and your function will work as expected.
const scores = [35, 68, 70, 38];
const scores1 = [89, 42, 33];
function gradingStudents(grades) {
const newScores = grades.map(function (grade) {
if (grade + 2 >= 40 && grade % 5 >= 3) {
return grade % 5 == 3 ? grade + 2 : grade + 1;
} else if (grade + 2 >= 40 && grade % 5 < 3) {
return grade;
} else {
return grade;
}
});
return newScores;
}
console.log(gradingStudents(scores1));
If you are handling the function using Rest Paramanter syntax as you did now, the parameter in the function written as ...grades will combine all the paramaters in the function to a single array. Which means your paramater scores1 will be there inside the grades array as in the below console.
const scores1 = [89, 42, 33];
function gradingStudents(...grades) {
// grades will be an array with scores1 as a sigle element in 0th index
console.log(grades)
}
gradingStudents(scores1);
Looping through grades in the above condition, the each node will be an array which will not satisfy any of the if statement, hence it will return the array itself. Thats why you are getting the output as an array with the parementer as the single node.
When declaring your function with rest parameters, you're expected to give your data as multiple arguments that will be automatically wrapped in an array
When giving it an array, you'l get a nested array
function restParamFunc(...params) {
console.log(params)
}
restParamFunc([1, 2])
You should either transform the rest parameters to a classic parameter
function restParamFunc(params) {
console.log(params)
}
restParamFunc([1, 2])
or use array destructuring when calling the function
function restParamFunc(...params) {
console.log(params)
}
restParamFunc(...[1, 2])
since you are returning grade if the first condition didn't meet. The rest operator is not needed. You can write it as follow:
function gradingStudents(grades) {
const newScores = grades.map(function (grade) {
if (grade + 2 >= 40 && grade % 5 >= 3) {
return grade % 5 == 3 ? grade + 2 : grade + 1;
}else {
return grade;
}
});
return newScores;
}
You can use forEach also
const scores = [35, 68, 70, 38];
const scores1 = [89, 42, 33];
function gradingStudents(grades) {
let newScore = [];
grades.forEach(function (grade) {
if (grade + 2 >= 40 && grade % 5 >= 3) {
grade = grade % 5 == 3 ? grade + 2 : grade + 1;
newScore.push(grade);
} else if (grade + 2 >= 40 && grade % 5 < 3) {
newScore.push(grade);
} else {
newScore.push(grade);
}
});
return newScore;
}
console.log(gradingStudents(scores));
console.log(gradingStudents(scores1));

How to add suffixes to an amount of money in javascript

I have a game where you earn money, and it is very easy to get rich. I want to make it so that if you get money more than a million, instead of showing 1234567, it shows 1.2 million. The process I am trying to go for if the number is more than a million is:
1: get the first two digits
2: remove the first two digits
3: store the remaining digits into a list
4: divide the length of the list by 3
5: get that value in the list of suffixes - 1 (because lists start at 0, not 1)
I can make the list of suffixes, I just need help on how to make this process.
This might be a good starting place for you. Let me know if it helps.
const $ = s => [...document.querySelectorAll(s)];
function formatNumber(n) {
if (n > 10**9 - 1) {
return (n / 10**9).toFixed(2) + "b"
} else if (n > 10**6 - 1) {
return (n / 10**6).toFixed(2) + "m"
} else {
return n
}
}
$("button")[0]
.addEventListener("click", e => {
const userInput = $("input")[0].value;
const formattedNumber = formatNumber(userInput);
$("#display")[0].innerText = formattedNumber;
});
body {
font-size: 2em;
}
<input type="number">
<button>Go</button>
<div id="display">output</div>
Here's an efficient approach that doesn't require any parsing - just simple string manipulation:
Get the digits greater before the 6 digit mark by subtracting the length of the string by 6
For the digit immediately after the 6 digit mark, you can use charAt and get the character at the index of the length of the string minus 6
Result:
const num = "13356789";
function wordify(number) {
if (number.length > 6) {
const start = num.substring(0, number.length - 6);
const second = num.charAt(number.length - 6);
return `${start}.${second} million`;
}
}
console.log(wordify(num));
Try it yourself with custom numbers:
function wordify(number) {
if (number.length > 6) {
const start = number.substring(0, number.length - 6);
const second = number.charAt(number.length - 6);
return `${start}.${second} million`;
}else{
return `number must have at least 6 digits`;
}
}
num.addEventListener('input', () => {
result.innerHTML = wordify(num.value);
});
Enter a number: <input id="num" type="number"><br/><br/> Result: <span id="result"></span>
Handling all cases (thousands, millions and billions):
let money = 1234567;
let strMoney = String(money);
if(strMoney.length >= 7 && strMoney.length <= 9) {
console.log(Math.round(money/ 1000000 * 100)/100, 'million')
}else if(strMoney.length > 9) {
console.log(Math.round(money/ 1000000000 * 100)/100, 'billion')
}else if(strMoney.length <= 6 && strMoney.length >= 4){
console.log(Math.round(money/ 1000 * 100)/100, 'thousand')
}else {
console.log(money)
}

How can I convert these 'if' statements to an algorithm

I'm trying to convert these 'if' statements to an algorithm, so that I can have many more stages instead of being limited to 10. How would I go about converting it? I just can't wrap my head around the logic!
function getStage(km) {
if (km > 2 && km < 4){
return 1;
}
else if (km > 4 && km < 6){
return 2;
}
else if (km > 6 && km < 8){
return 3;
}
else if (km > 8 && km < 10){
return 4;
}
else if (km > 10 && km < 12){
return 5;
}
else if (km > 12 && km < 14){
return 6;
}
else if (km > 14 && km < 16){
return 7;
}
else if (km > 16 && km < 18){
return 8;
}
else if (km > 18 && km < 20){
return 9;
}
else if (km > 20 && km < 22){
return 10;
}
}
I have tried this:
function getStage(km) {
var tempStage = 0;
for (var i = 0; i < stages; i++) {
var stage = i + 1;
var tempKm = stage * 2;
var nextKm = stage + 2;
if (km > tempKm && km < nextKm) {
tempStage = stage;
}
}
return tempStage;
}
Perhaps I shouldn't be using a for loop? Is there a better way of doing this?
Maybe you are looking for Math.floor
function getStage(km) {
return Math.floor(km / 2)
}
console.log(getStage(2));
// 1
console.log(getStage(10));
// 5
console.log(getStage(11));
// 5
You can just use math to do this. No loops or conditionals necessary.
Notice that your input intervals increase in "steps" of 2, and your outputs increase in "steps" of 1. This makes me think maybe we should divide km by 2.
Since we always want an integer answer, we can use the Math.floor function.
Some examples:
Math.floor(3/2) = 1
Math.floor(4.1/2) = 2
etc.
Depending on what you want to return for edge cases (what if km = 2 or km = 4, or any multiple of 2?) we might be done here. If you wish to return 1 when k=4, 2 when k=6, etc., you'll need to do a little more work.
*** In general: *** if you are working with numbers and you find yourself writing a lot of cases, you can usually use some combination of simple mathematical operators to calculate the result. For problems like these, try thinking about your input/output pairs, and what the relationship is between them.
You could take the floored value of km divided by two plus one.
10 is the upper limit.
function getStage(km) {
return Math.min((km >> 1) + 1, 10);
}
console.log(getStage(2.1)); // 2
console.log(getStage(3)); // 2
console.log(getStage(4)); // 4
Try something like this. This is general solution which applies not only to 2*n series.
const stages = [2, 4, 6, 8, 10, 13, 15, 16, 20]; //should be ordered. Else sort it first.
const getStage = km => stages.indexOf(stages.find(i => km < i));
console.log(getStage(5)); //2
console.log(getStage(1.5)); //0
console.log(getStage(8.1)); //4
console.log(getStage(15)); //7
console.log(getStage(22)); //-1 out of index

Rounding up to the nearest multiple of 5

I am trying to write a Javascript function rounding up to the nearest multiple of 5. But you only round up if the difference between the variable and the roundup to the multiple of 5 is less than 3. (so 53 would round up to 55, but 52 would stay 52.)
Also if the grade is < 38 its an F.
The code below is what I have but it is not running properly. How can I fix it?
Thanks!!
grade = 71
function roundGrade (grade) {
const remainder = grade % 5
if (grade < 38) {
return "fail"; }
else if (remainder >= 3) {
grade; }
else if (remainder < 3) {
grade-remainder+5
}
}
If the remainder is 3 or above, you simply need to add 5 and subtract the remainder, which can be done with grade += 5 - remainder. Also note that you don't need your second else if conditional at all, as you only want to modify grade if the remainder is greater than or equal to 3. Finally, you need to make sure that your function actually returns grade with return grade.
This can be seen in the following:
function roundGrade(grade) {
const remainder = grade % 5;
if (grade < 38) {
return "fail";
} else if (remainder >= 3) {
grade += 5 - remainder;
}
return grade;
}
console.log(roundGrade(71));
console.log(roundGrade(74));
calculate the remainder of grade / 5 and add it to the grade if the remaining is less than 3, otherwise return the grade as is.
const grade1 = 71
const grade2 = 73
const grade3 = 33
function roundGrade(grade) {
if (grade < 38) return "fail"
const rem = grade % 5;
return rem < 3 ? grade : grade + (5 - rem)
}
console.log(roundGrade(grade1))
console.log(roundGrade(grade2))
console.log(roundGrade(grade3))

Categories

Resources