Javascript - How should I calculate the result use for loop? - javascript

Suppose a carpark charges a $2 minimum fee to park for up to 3 hours, then the carpark charges an additional $0.5 per hour for each hour. For example, park for 5 hours charge $2+$0.5+$0.5=$3
How should I calculate the fee use for loop?

There's no need to use a for loop:
function calculateFee(hours) {
if (isNaN(hours) || hours <= 0) return 0;
if (hours <= 3) return 2;
var additionalHours = Math.round(hours - 3);
return 2 + 0.5 * additionalHours;
}
var fee = calculateFee(5);
And if using a for loop is a requirement:
function calculateFee(hours) {
if (isNaN(hours) || hours <= 0) return 0;
var result = 2;
if (hours <= 3) return result;
var additionalHours = Math.round(hours - 3);
for (i = 0; i < additionalHours; i++) {
result += 0.5;
}
return result;
}
And finally an example using objects:
function FeeCalculator(minimalFee, initialHours, additionalHourFee) {
if (isNaN(minimalFee) || minimalFee <= 0) { throw "minimalFee is invalid"; }
if (isNaN(initialHours) || initialHours <= 0) { throw "initialHours is invalid"; }
if (isNaN(additionalHourFee) || additionalHourFee <= 0) { throw "additionalHourFee is invalid"; }
this.minimalFee = minimalFee;
this.initialHours = initialHours;
this.additionalHourFee = additionalHourFee;
}
FeeCalculator.prototype = {
calculateFee: function(hours) {
if (hours <= this.initialHours) return this.minimalFee;
var additionalHours = Math.round(hours - this.initialHours);
return this.minimalFee + this.additionalHourFee * additionalHours;
}
};
var calculator = new FeeCalculator(2, 3, 0.5);
var fee = calculator.calculateFee(5);

May be like this, sorry If it is wrong, coz I didnt test it.
fee=0
if (hour>0){
fee=2;
hour-=3;
//without for loop
//if(hour>0)fee+=0.5*hour;
//with for loop
for(var i=0;i<hour;i++){
fee+=0.5;
}
}
return fee;

Related

I want to check the grade of the students marks , based on average

What's wrong with this code? I tried get marks using array and pass the array in to function parameters and calculate the average in that function.
const marks = [100,100,80];
var summ = 0;
function calculateGrade(){
for(let i=0; i<=marks.length;i++){
summ = summ+marks[i];
var avg = (summ/marks.length);
}
if(avg<=59){
console.log('F');
}
else if(avg>=60 && avg<=69){
console.log('D');
}
else if(avg>=70 && avg<=79){
console.log('C');
}
else if(avg>=80 && avg<=89){
console.log('B');
}
else if(avg>=90 && avg<=100){
console.log('A');
}
}
console.log(calculateGrade(marks));
const sum = marks.reduce((partialSum, a) => partialSum + a, 0);
const marks = [100, 100, 80];
var summ = 0;
//issue one (Tmarks were missing )
function calculateGrade(Tmarks) {
// issues 2 ( <= should be < )
for (let i = 0; i < Tmarks.length; i++) {
summ += Tmarks[i];
}
var avg = summ / Tmarks.length;
if (avg <= 59) {
console.log("F");
} else if (avg >= 60 && avg <= 69) {
console.log("D");
} else if (avg >= 70 && avg <= 79) {
console.log("C");
} else if (avg >= 80 && avg <= 89) {
console.log("B");
} else if (avg >= 90 && avg <= 100) {
console.log("A");
}
}
console.log(calculateGrade(marks));
Following were the issues in your code
You were not getting the parameters in function definition
issues 2 ( <= should be < )
You just added an extra = in your for loop
i<=marks.length
instead of
i<marks.length
So while calculating the sum & average, a garbage value gets added up.
You are very close
const marks = [100, 100, 80];
function calculateGrade(marks) {
let summ = 0;
for (let i = 0; i < marks.length; i++) {
summ += marks[i];
}
const avg = summ / marks.length;
let grade = '';
if (avg < 59) {
grade = 'F';
} else if (avg <= 69) {
grade = 'D';
} else if (avg <= 79) {
grade = 'C';
} else if (avg <= 89) {
grade = 'B';
} else {
grade = 'A';
}
return grade;
}
console.log(calculateGrade(marks));
There are couple of mistakes in your code.
1.
for(let i=0; i<=marks.length;i++)
marks.length is 3. Array index starting from 0.
const marks = [100,100,80];
index 0 is 100.
index 1 is 100.
index 2 is 80.
When you add i<=marks.length, this is equals to i<=3.
= in here will run the loop extra circle and this will return NaN because there are only 3 elements in you array and array indexing is 0 based.
2.
for(let i=0; i<=marks.length;i++){
summ = summ+marks[i];
var avg = (summ/marks.length);
}
avg is out of scope. you have defined avg inside the loop and trying to access it outside of the loop. Anything declared in the loop is scoped to that loop and are not available outside the loop.
3.
console.log(calculateGrade(marks));
Your calculateGrade() function is not accepting any parameters. So you can't pass any parameter into this function.
4.
console.log(calculateGrade(marks));
since calculateGrade() function is not returning any value, this will print nothing. So you don't need to call this inside a console.log();.
I have simplified your code as below.
const marksArr = [100, 100, 80];
calculateGrade(marksArr);
function calculateGrade(marks) {
console.log('calling calculateGrade(marks)...');
var avg = (marksArr.reduce(function(a, b) {
return a + b;
}, 0)) / marksArr.length;
console.log('avg is', avg);
if (avg <= 59) {
console.log('Grade', 'F');
} else if (avg >= 60 && avg <= 69) {
console.log('Grade', 'D');
} else if (avg >= 70 && avg <= 79) {
console.log('Grade', 'C');
} else if (avg >= 80 && avg <= 89) {
console.log('Grade', 'B');
} else if (avg >= 90 && avg <= 100) {
console.log('Grade', 'A');
}
}
` calculateGrade(){
let marks = [100,100,80];
let summ = 0;
let avg = 0;
for(let i = 0; i < marks.length; i++){
summ = summ+marks[i];
avg = (summ/marks.length);
}
if(avg<=59){
console.log('F');
}
else if(avg>=60 && avg<=69){
console.log('D');
}
else if(avg>=70 && avg<=79){
console.log('C');
}
else if(avg>=80 && avg<=89){
console.log('B');
}
else if(avg>=90 && avg<=100){
console.log('A');
}
}`
> array start from 0

Problem with Javascript function not returning total sum in a for loop with if conditions

I am writing pure javascript without any HTML and I am having trouble with one of my functions that would need to return the total "course points."
The program consists of prompting the user the # of course taken followed by the grade received which is pushed in the "grades" array. The function calculateCP will allow it to reiterate every element of the array and is suppose to give me the total course points given the following if conditions.
Please help why my function isn't working! The output is returning only the first element of the array, not the total sum of all elements.
calculateCP = () => {
let coursePoints;
let total = 0;
for (let i = 0; i < grades.length; i++) {
if (grades[i] >= 90) {
coursePoints = 4;
} else if (grades[i] >= 80 && grades[i] < 90) {
coursePoints = 3;
} else if (grades[i] >= 70 && grades[i] < 80) {
coursePoints = 2;
} else if (grades[i] >= 60 && grades[i] < 70) {
coursePoints = 1;
} else if (grades[i] < 60) {
coursePoints = 0;
}
return total = total + coursePoints;
}
}
const grades = [];
let noOfCourses = parseInt(prompt("Please enter # of courses taken: "));
console.log("\n")
for (let i = 0; i < noOfCourses; i++) {
grades.push(prompt('Enter grade recieved '));
}
console.log(calculateCP());
}
In the for loop you just want to sum the values.. only once you're done, return the total :) something like this..
calculateCP = () => {
let coursePoints;
let total = 0;
for (let i = 0; i < grades.length; i++) {
if (grades[i] >= 90) {
coursePoints = 4;
} else if (grades[i] >= 80 && grades[i] < 90) {
coursePoints = 3;
} else if (grades[i] >= 70 && grades[i] < 80) {
coursePoints = 2;
} else if (grades[i] >= 60 && grades[i] < 70) {
coursePoints = 1;
} else if (grades[i] < 60) {
coursePoints = 0;
}
total = total + coursePoints;
}
return total;
}
const grades = [];
let noOfCourses = parseInt(prompt("Please enter # of courses taken: "));
console.log("\n")
for (let i = 0; i < noOfCourses; i++) {
grades.push(prompt('Enter grade recieved '));
}
console.log(calculateCP());
}
try to remove the return statement from the for loop and put it right after it..
change this:
return total = total + coursePoints;
to this:
... for loop
total = total + coursePoints;
}
return total;

If Statement Returning True for Wrong Statement

Wrote a simple little app to check what period it is a display it with Javascript. Works great for the most part - but at certain times it will display the next period instead of the current one.
How do I test it without waiting and manually checking?
I'd obviously like to figure out why it displays the wrong period
Edit: If the time is 15:06 (3:06PM) it will display the last else statement instead of the second to last one
Code:
var now = '';
//Set Periods
//Slot 1+2 are periods - slots 3+4 are passing times inbetween periods
var periods = [
['Before School', 5.00, 7.59],
['First', 8.00, 8.49, 8.50, 8.54],
['Second', 8.55, 9.44, 9.45, 9.49],
['Third', 9.50, 10.39, 10.40, 10.44],
['Fourth', 10.45, 11.34, 11.35, 11.39],
['Fifth', 11.40, 12.29, 12.30, 12.34],
['Sixth', 12.35, 13.24, 13.25, 13.29],
['Seventh', 13.30, 14.19, 14.20, 14.24],
['Eighth', 14.25, 15.15]
];
//Display Period
function displayPeriod() {
if (now >= periods[0][1] && now <= periods[0][2]) {
document.getElementById('period').innerHTML = ('School has not started yet');
} else if (now >= periods[1][1] && now <= periods[1][2]) {
document.getElementById('period').innerHTML = ('1st');
} else if (now >= periods[1][3] && now <= periods[1][4]) {
document.getElementById('period').innerHTML = ('1st Passing');
} else if (now >= periods[2][1] && now <= periods[2][2]) {
document.getElementById('period').innerHTML = ('2nd');
} else if (now >= periods[2][3] && now <= periods[2][4]) {
document.getElementById('period').innerHTML = ('2nd Passing');
} else if (now > periods[3][1] && now <= periods[3][2]) {
document.getElementById('period').innerHTML = ('3rd');
} else if (now >= periods[3][3] && now <= periods[3][4]) {
document.getElementById('period').innerHTML = ('3rd Passing');
} else if (now >= periods[4][1] && now <= periods[4][2]) {
document.getElementById('period').innerHTML = ('4th');
} else if (now >= periods[4][3] && now <= periods[4][4]) {
document.getElementById('period').innerHTML = ('4th Passing');
} else if (now >= periods[5][1] && now <= periods[5][2]) {
document.getElementById('period').innerHTML = ('5th');
} else if (now >= periods[5][3] && now <= periods[5][4]) {
document.getElementById('period').innerHTML = ('5th Passing');
} else if (now >= periods[6][1] && now <= periods[6][2]) {
document.getElementById('period').innerHTML = ('6th');
} else if (now >= periods[6][3] && now <= periods[6][4]) {
document.getElementById('period').innerHTML = ('6th Passing');
} else if (now >= periods[7][1] && now <= periods[7][2]) {
document.getElementById('period').innerHTML = ('7th');
} else if (now >= periods[7][3] && now <= periods[7][4]) {
document.getElementById('period').innerHTML = ('7th Passing');
} else if (now >= periods[8][1] && now <= periods[8][2]) {
document.getElementById('period').innerHTML = ('8th');
} else {
document.getElementById('period').innerHTML = ('School is done for the day.');
}
}
//Check Time
function startTime() {
var today = new Date();
now = today.getHours() + '.' + today.getMinutes();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
displayPeriod();
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) {
i = '0' + i
}; // add zero in front of numbers < 10
return i;
}
You can test the function by inputting the current time through startTime() function. You can comment out the setTimeout if you only want to test a specific function. You can check that the output for 15.06 is correct too.
var now = '';
//Set Periods
//Slot 1+2 are periods - slots 3+4 are passing times inbetween periods
var periods = [
['Before School', 5.00, 7.59],
['First', 8.00, 8.49, 8.50, 8.54],
['Second', 8.55, 9.44, 9.45, 9.49],
['Third', 9.50, 10.39, 10.40, 10.44],
['Fourth', 10.45, 11.34, 11.35, 11.39],
['Fifth', 11.40, 12.29, 12.30, 12.34],
['Sixth', 12.35, 13.24, 13.25, 13.29],
['Seventh', 13.30, 14.19, 14.20, 14.24],
['Eighth', 14.25, 15.15]
];
//Display Period
function displayPeriod() {
console.log(now)
if (now >= periods[0][1] && now <= periods[0][2]) {
console.log('School has not started yet');
} else if (now >= periods[1][1] && now <= periods[1][2]) {
console.log('1st');
} else if (now >= periods[1][3] && now <= periods[1][4]) {
console.log('1st Passing');
} else if (now >= periods[2][1] && now <= periods[2][2]) {
console.log('2nd');
} else if (now >= periods[2][3] && now <= periods[2][4]) {
console.log('2nd Passing');
} else if (now > periods[3][1] && now <= periods[3][2]) {
console.log('3rd');
} else if (now >= periods[3][3] && now <= periods[3][4]) {
console.log('3rd Passing');
} else if (now >= periods[4][1] && now <= periods[4][2]) {
console.log('4th');
} else if (now >= periods[4][3] && now <= periods[4][4]) {
console.log('4th Passing');
} else if (now >= periods[5][1] && now <= periods[5][2]) {
console.log('5th');
} else if (now >= periods[5][3] && now <= periods[5][4]) {
console.log('5th Passing');
} else if (now >= periods[6][1] && now <= periods[6][2]) {
console.log('6th');
} else if (now >= periods[6][3] && now <= periods[6][4]) {
console.log('6th Passing');
} else if (now >= periods[7][1] && now <= periods[7][2]) {
console.log('7th');
} else if (now >= periods[7][3] && now <= periods[7][4]) {
console.log('7th Passing');
} else if (now >= periods[8][1] && now <= periods[8][2]) {
console.log('8th');
} else {
console.log('School is done for the day.');
}
}
//Check Time
function startTime(hours, minutes, seconds) {
var today = new Date();
var h = hours != null ? hours : today.getHours(); // use current time if input is empty
var m = minutes != null ? minutes : today.getMinutes(); // use current time if input is empty
var s = seconds != null ? seconds : today.getSeconds(); // use current time if input is empty
m = checkTime(m);
s = checkTime(s);
now = h + '.' + m; // move it here to correspond with input
displayPeriod();
// var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) {
i = '0' + i
}; // add zero in front of numbers < 10
return i;
}
startTime();
startTime(15, 6, 0);
You should check time (add zero in front of numbers < 10) before set now variable
function startTime() {
var today = new Date();
var h = checkTime(today.getHours());
var m = checkTime(today.getMinutes());
now = h + '.' + m;
displayPeriod();
var t = setTimeout(startTime, 500);
}
Where your problem is:
Your startTime function is setting now like this:
now = today.getHours() + '.' + today.getMinutes();
It's then calculating zero-padded hour and minute values, but these are not used!
So, instead of representing nine minutes past eight as "9.08", it is using "9.8".
How to test your code
You probably want to learn about unit testing, but that is too big a topic to go over here.
Some of the prinicpals of writing testable code can be applied here, though.
First, separate logic from updating UI (or DOM), by refactoring your DisplayPeriod function to return a string value instead of modifying the DOM:
function displayPeriod() {
if (now >= periods[0][1] && now <= periods[0][2]) {
return 'School has not started yet';
} else if (now >= periods[1][1] && now <= periods[1][2]) {
return '1st';
} else if (now >= periods[1][3] && now <= periods[1][4]) {
return '1st Passing';
} else if (now >= periods[2][1] && now <= periods[2][2]) {
return '2nd';
// (Snip)
} else {
return 'School is done for the day.';
}
}
This method would then be used by another method which updates the DOM.
Second, allow for injection of dependencies. E.g. You have an implicit dependency on the system clock via the Date() constructor. If you refactor StartTime to accept a date, then your test code can pass in whichever date values it needs to test different cases:
// Note that bugs in this method have not been fixed!
function startTime(today) {
now = today.getHours() + '.' + today.getMinutes();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
// Commented out, as interfers with testing (should be moved to DOM setting method).
// var t = setTimeout(startTime, 500);
}
Third, use a test framework to run various scenarios and check expected and actual results. Here's a poor man's test case and test execution script:
function TestCase(time, expectedResult) {
startTime(time)
var result = displayPeriod();
if (result == expectedResult) {
console.log("Passed for " + time)
} else {
console.log("Failed for " + time + "(" + result + ")");
}
}
for (minute = 0; minute < 50; minute++) {
time = new Date(2018, 11, 14, 8, minute);
TestCase(time, "1st");
}

How to create dynamic IF statement?

I want to make condition of IF statement dynamically in javascript
example :
function checkNumber(number) {
var dynamicStatement = 1000000; // IF statement stop 1 million
if(number <= 1000) {
return 1000;
} else if(number <= 2000)
return 2000;
} else if(number <= 3000)
return 3000;
} else if(number <= 4000)
return 4000;
} else if (...) {
return ...
} else if (number <= 1000000) {
return 1000000;
}
}
Please help, thank you.
You can use:
Math.ceil(number/1000)*1000;
This will return the value nearest to the multiplier with 1000. For eg. if number is 900 then it will return 1000, if number is 1050 it will return 2000 and so on.
function checkNumber(number, limit, step) {
for(let i = 0; i < limit; i = i+step) {
if(number <= i) {
return i;
}
}
throw "Invalid Number";
}
checkNumber(75006, 1000000, 1000)
That answer Bhojendra posted is simple and beautiful, it's probably the one that suits your situation best.
Here's another, using for-loop:
function checkNumber(number) {
var dynamicStatement = 1000000;
var thousands = dynamicStatement / 1000;
for(var i = 0; i<thousands; i++){
if(number <= thousands * i){
return thousands * i;
}
}
return -1;
}

Sort an array of objects by hour minutes in ascending order from earliest to latest

I have this code to sort an array of objects. The data in the objects is channel and time (hour, minutes). I want the sort to be by channels based on time from earliest to latest.
The channel data is accessed in this way:
channel_array[icount].data[0].hour
channel_array[icount].data[0].minutes
That data object array is like this and is already sorted:
[{hour:1, minutes:10},{hour:4, minutes:01}...]
Now all I need is to sort the channels from earliest to latest on the first element of the data array {hour:1, minutes: 10}. I do this with three nested loops. But this is not ideal. Is there a better way to do the sorting?
var current_time = new Date();
var current_hour = current_time.getHours();
var comp_hour = current_hour - 1;
for (var ih = 0; ih < 24; ih++) {
comp_hour += 1;
if (comp_hour == 24) { comp_hour = 0; }
for (var minutes = 0; minutes < 60; minutes++) {
for (var icount = 0; icount < channel_array.length; icount++) {
if (channel_array[icount].data.length > 0) {
var channel_hour = channel_array[icount].data[0].hour;
var channel_minutes = channel_array[icount].data[0].minutes;
var channel_phase = channel_array[icount].data[0].phase;
var next_day = channel_array[icount].data[0].next_day;
if (channel_phase.toLowerCase() == "pm" && channel_hour != 12) { channel_hour += 12; }
if ( parseInt(channel_hour) == parseInt(comp_hour) && parseInt(channel_minutes) == parseInt(minutes) && next_day != 1 ) {
channel_array_sort.push(channel_array[icount]);
}
}
}
}
}
Good lord, this is overcomplicated! How about just passing a custom comparator to Array.sort?
I'm honestly having a hard time figuring out exactly which array you are trying to sort, but in general, it would look something like this:
var input = [{hour:1, minutes:10},{hour:4, minutes: 1}, ...];
input.sort(function (a, b)
{
// compare hours first
if (a.hour < b.hour) return -1;
if (a.hour > b.hour) return 1;
// else a.hour === b.hour, so compare minutes to break the tie
if (a.minute < b.minute) return -1;
if (a.minute > b.minute) return 1;
// couldn't break the tie
return 0;
});
N.B. this performs an in-place sort, which means that the original array is modified. If that's not acceptable, just make a copy of the array before sorting it.
var input = /* same as before */;
var output = input.concat();
output.sort(function ()
{
// same as before
});
Starting point for the solution, from the OP:
channel_array_sort = channel_array.concat();
channel_array_sort.sort(function (a, b)
{
if (a.data == undefined || b.data == undefined) return 0;
if (a.data.length <= 0 || b.data.length <= 0) return 0;
// compare hours first
var a_hour = a.data[0].hour;
if (a.data[0].phase == "pm") a_hour += 12;
var b_hour = b.data[0].hour;
if (b.data[0].phase == "pm") b_hour += 12;
if (a_hour < b_hour) return -1;
if (a_hour > b_hour) return 1;
// else a.hour === b.hour, so compare minutes to break the tie
if (a.data[0].minutes < b.data[0].minutes) return -1;
if (a.data[0].minutes > b.data[0].minutes) return 1;
// couldn't break the tie
return 0;
});
var print_sort = JSON.stringify(channel_array_sort);
alert('print_sort b '+print_sort);

Categories

Resources