Stuck on Java program that tallies grades and shows results - java

I'm taking a beginners course in Java and they asked us to:
Write a program to tally the number of A's, B's, C's, D's and F's based upon a list of scores entered by a user.
After all the scores are entered, the program must display a
horizontal bar graph of the number tallied for each grade like that shown in the Operation section.
The tally graph must display a single '*' for each unit tallied.
When a user enters a -1, the program must display the final graph and
exit.
The output of your program must display prompts and a tally graph
like that shown in the Operation section above.
You may assume that a user will enter numbers only.
Operation:
The program starts and prompts you to either enter a test score or end
the program by entering a -1. Like the following:
Number of A's: 0
Number of B's: 0
Number of C's: 0
Number of D's: 0
Number of F's: 0
Enter a score (%) or -1 to end: 90
As you enter each score, the application decides whether the score is
an A, B, C, D or F and adds one to the letter-grade tally. Like the
following:
Number of A's: 1
Number of B's: 0
Number of C's: 0
Number of D's: 0
Number of F's: 0
Enter a score (%) or -1 to end: 95
Each time you enter a score, the program updates the tally. Like the following:
Number of A's: 2
Number of B's: 0
Number of C's: 0
Number of D's: 0
Number of F's: 0
Enter a score (%) or -1 to end: -1
When you are done entering scores, the program displays a horizontal
bar graph of the tally for A's, B's, C's, D's and F's. Like the
following:
A's: **
B's:
C's:
D's:
F's:
Specifications:
Numerical Grade Letter Grade
greater than or equal to 90 A
less than 90 but greater than or equal to 80 B
less than 80 but greater than or equal to 70 C
less than 70 but greater than or equal to 60 D
less than 60 F
When the program ends, display the number of scores, average score, and best score.
Example:
Number of scores: 2
Average score: 92.5
Best score: 95.0
We have also been instructed to code in at least two methods : one that has a void and one that returns something.
So far I have only been able to tally up the scores entered, but I don't seem to be able to wrap my head around recording all the inputs and calculating the average and picking out the best score
This is what I have so far :
import java.util.*;
public class ScoreTally {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int aCount = 0;
int bCount = 0;
int cCount = 0;
int dCount = 0;
int fCount = 0;
int scoreCount = -1;
double score = 0;
while (score != -1) {
if (score >= 90)
aCount++;
else if ((score < 90) && (score >= 80))
bCount++;
else if ((score < 80) && (score >= 70))
cCount++;
else if ((score < 70) && (score >= 60))
dCount++;
else if ((score < 60) && (score > 0))
fCount++;
System.out.println("Number of A's: " + aCount);
System.out.println("Number of B's: " + bCount);
System.out.println("Number of C's: " + cCount);
System.out.println("Number of D's: " + dCount);
System.out.println("Number of F's: " + fCount);
System.out.print("Enter a score (%) or -1 to end: ");
score = input.nextDouble();
scoreCount++;
}
if (score == -1)
System.out.println("Number of scores: " + scoreCount);
}
}

Use a function to return the greatest number to get your best score.
And another function to print the final graph.
That should take care of the two function requirement.
Also, make the loop an exit-controlled one, as it has to run atleast once.
As a coding practice, you should not be using star imports(import java.util.*) instead use only what you need.
Also, good work on setting the scoreCount to -1 in the beginning.
import java.util.Scanner;
public class ScoreTally {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int aCount = 0;
int bCount = 0;
int cCount = 0;
int dCount = 0;
int fCount = 0;
int scoreCount = -1;
double score;
double totalScore = 0;
double bestScore = -1;
do {
System.out.println("Number of A's: " + aCount);
System.out.println("Number of B's: " + bCount);
System.out.println("Number of C's: " + cCount);
System.out.println("Number of D's: " + dCount);
System.out.println("Number of F's: " + fCount);
System.out.print("Enter a score (%) or -1 to end: ");
score = input.nextDouble();
if (score >= 90) {
aCount++;
} else if ((score < 90) && (score >= 80)) {
bCount++;
} else if ((score < 80) && (score >= 70)) {
cCount++;
} else if ((score < 70) && (score >= 60)) {
dCount++;
} else if ((score < 60) && (score > 0)) {
fCount++;
}
scoreCount++;
totalScore = totalScore + score;
bestScore = greaterNumber(bestScore, score);
} while (score != -1);
printGraph('A', aCount);
printGraph('B', bCount);
printGraph('C', cCount);
printGraph('D', dCount);
printGraph('F', fCount);
System.out.println("Number of scores: " + scoreCount);
System.out.println("Average scores: " + totalScore / scoreCount);
System.out.println("Best scores: " + bestScore);
}
public static void printGraph(char grade, int count) {
System.out.print("Number of " + grade + "'s: ");
for (int i = 0; i < count; i++) {
System.out.print("*");
}
System.out.println();
}
public static double greaterNumber(double firstNum, double secondNum) {
if (firstNum >= secondNum) {
return firstNum;
} else {
return secondNum;
}
}
}

To begin with you already have the code to tally the results.
int aCount = 0;
int bCount = 0;
int cCount = 0;
int dCount = 0;
int fCount = 0;
int scoreCount = -1;
What you need is another field that will hold the total score i.e.
int totalScore = 0;
You need to prompt for the first score before you enter the while loop otherwise it won't run properly the first iteration. At the end (or the beginning) you need to update totalScore with whatever was the input for that round, and not update it if the input was -1.
The average score will just be the totalScore/scoreCount you should compute that after you finish the while loop.
For the best score you can have another field for int = maxScore
you can update it every iteration of the loop with
maxScore = Math.max(maxScore, score);
Math.max returns the maximum of the two numbers.

It's rather simple. Declare 2 variables, one for having avgScore, one for in beginning of your program.
double bestScore = 0.0;
double avgScore = 0.0;
double totalScore = 0.0;
while (score != -1) {
totalScore = totalScore + score;
if(score > bestScore)
bestScore = score;
if (score >= 90)
aCount++;
else if ((score < 90) && (score >= 80))
bCount++;
else if ((score < 80) && (score >= 70))
cCount++;
else if ((score < 70) && (score >= 60))
dCount++;
else if ((score < 60) && (score > 0))
fCount++;
System.out.println("Number of A's: " + aCount);
System.out.println("Number of B's: " + bCount);
System.out.println("Number of C's: " + cCount);
System.out.println("Number of D's: " + dCount);
System.out.println("Number of F's: " + fCount);
System.out.print("Enter a score (%) or -1 to end: ");
score = input.nextDouble();
scoreCount++;
}
if (score == -1){
System.out.println("Number of scores: " + scoreCount);
avgScore = totalScore/scoreCount;
System.out.println("Best Score: " + bestScore);
System.out.println("Avg Score: " + avgScore);
}
Also for displaying the chart you can use your final tallies.

Related

Read Scores from text file and sort into array

Im trying to get my test score program to work. Whenever I type in the pathfile to read from the text file the program would read 4 out of the 5 numbers that are there.Also, no matter what number there are it is always going to display my minimum as 0 when it is not true. Any help is truly appreciated!
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Scanner;
public class Exam{
public static void main(String[] args) throws IOException {
System.out.println("Welcome!" + "\n");
//File location
System.out.println("Where is the data file:");
Scanner userInput = new Scanner(System.in);
String userFile = userInput.nextLine();
int i = 0;
int scores[] = readScores(userFile);
System.out.println("Minimum score: " + scores[0]);
System.out.println("Maximum score: " + scores[(scores.length - 1)]);
//Average Calculation
double gradesTotal = 0;
for (i=0; i<scores.length; ++i){
gradesTotal = gradesTotal + scores[i];
}
double mean = gradesTotal/scores.length;
System.out.println("Average score: " + mean);
//Mean Calculation
double median;
if (scores.length % 2 == 0)
median = ((scores[(scores.length/2) - 1]) + scores[(scores.length/2)]) / 2;
else
median = scores[(scores.length/2)];
System.out.println("Median score: " + median + "\n");
//Number of Grades
int gradeA = 0;
int gradeB = 0;
int gradeC = 0;
int gradeD = 0;
int gradeF = 0;
for (i=0; i<scores.length; i++)
{
if (scores[i] >= 90 && scores[i] <=100){
gradeA++;
}
else if (scores[i] <= 89 && scores[i] >=80){
gradeB++;
}
else if (scores[i] <= 79 && scores[i] >=70){
gradeC++;
}
else if (scores[i] <= 69 && scores[i] >=60){
gradeD++;
}
else if (scores[i] <= 59 && scores[i] >=1){
gradeF++;
}
}
System.out.println("Scores by letter grade: ");
System.out.println("A: " + gradeA);
System.out.println("B: " + gradeB);
System.out.println("C: " + gradeC);
System.out.println("D: " + gradeD);
System.out.println("F: " + gradeF);
}
//Reads the data from the submitted file
private static int[] readScores(String userFile) throws FileNotFoundException
{
File inputFile = new File(userFile);
Scanner stats = new Scanner(inputFile);
try {
int scores[] = new int[stats.nextInt()];
int i = 0;
while (stats.hasNext()){
scores[i] = stats.nextInt();
i++;
}
System.out.println("\n" + "There are " + (i) + " scores" + "\n");
Arrays.sort(scores);
return scores;
}
finally {
stats.close();
}
}
}
Text file:
72
31
13
39
74
Program output:
There are 4 scores
Minimum score: 0
Maximum score: 74
Average score: 2.1805555555555554
Median score: 0.0
Number of scores by letter grade:
A: 0
B: 0
C: 1
D: 0
F: 3
int scores[] = new int[stats.nextInt()];
here you take the first of your values and then you dont have it where you need it.
That is probably also the reason why your calculations are so messed up. you create an array of lenght 72 and use that lenght for the number of values.
Maybe you want to use a list instead. It allows you to add as many values as you want without specifying a number like you have to do when you use an array.

How to print proper minimum and maximum from user input

I am trying to write a program that allows a user to enter in a number of random grades they want to display along with the sum, average, minimum and maximum of the generated list. The grades range from 60 - 100.
The program is printing the min properly and the sum is adding up the previously generated sum along with the newly generated one. How can I change it so that it give the correct output for the minimum and so that is stops adding the previou sum to the new one? Any help would be appreciated.
The image link for the output shows the minimum output issue. The min should be 66.0 but it says 59.0.
output
import java.util.Scanner;
public class A03C
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.print("How many scores? ");
int howMany = input.nextInt();
double score = 0;
double sum = 0;
double average = 0;
double max = 0;
double min = 60;
while (howMany > 0)
{
for (int i = 1; i <= howMany; i++)
{
score = 60 + (int)(Math.random() * ((100 - 60) +1));
if (letterGrade(score));
sum += score++;
average = (sum/howMany);
if (score > max)
max = score;
if (score < max)
min = score;
}
System.out.println("Sum: " + sum);
System.out.println("Average: " + average);
System.out.println("Max: " + (max - 1));
System.out.println("Min: " + (min - 1));
System.out.println("How many scores? ");
howMany = input.nextInt();
}
}
public static boolean letterGrade(double score)
{
if (score >= 92.0)
System.out.println(score + " is an A");
else if (score >= 83.0)
System.out.println(score + " is a B");
else if (score >= 75.0)
System.out.println(score + " is a C");
else
System.out.println(score + " is an F");
return false;
}
}
Just clean the sum variable after the execution, also I changed the return of the letterGrade to true:
import java.util.Scanner;
public class A03C {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("How many scores? ");
int howMany = input.nextInt();
double score = 0;
double sum = 0;
double average = 0;
double max = 0;
double min = 60;
while (howMany > 0) {
for (int i = 1; i <= howMany; i++) {
score = 60 + (int) (Math.random() * ((100 - 60) + 1));
if (letterGrade(score))
sum += score++;
average = (sum / howMany);
if (score > max)
max = score;
if (score < max)
min = score;
}
System.out.println("Sum: " + sum);
System.out.println("Average: " + average);
System.out.println("Max: " + (max - 1));
System.out.println("Min: " + (min - 1));
System.out.println("How many scores? ");
sum = 0;
howMany = input.nextInt();
}
}
public static boolean letterGrade(double score) {
if (score >= 92.0)
System.out.println(score + " is an A");
else if (score >= 83.0)
System.out.println(score + " is a B");
else if (score >= 75.0)
System.out.println(score + " is a C");
else
System.out.println(score + " is an F");
return true;
}
}
Before continue, i definitely think that you should read #joe C comment.
As i understand you are a beginner, i will explain the changes i did.
import java.util.Scanner;
public class A03C
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.print("How many scores? ");
int howMany = = input.nextInt();
double score = 0;
double sum = 0;
double average = 0;
double max = 60;
double min = 100;
while (howMany > 0)
{
for (int i = 1; i <= howMany; i++)
{
score = 60 + (int)(Math.random() * ((100 - 60) +1));
letterGrade(score);
sum += score++;
average = (sum/howMany);
if (score > max)
max = score;
if (score < min)
min = score;
}
System.out.println("Sum: " + sum);
System.out.println("Average: " + average);
System.out.println("Max: " + (max - 1));
System.out.println("Min: " + (min - 1));
System.out.println("How many scores? ");
howMany = input.nextInt();
}
}
public static void letterGrade(double score)
{
if (score >= 92.0)
System.out.println(score + " is an A");
else if (score >= 83.0)
System.out.println(score + " is a B");
else if (score >= 75.0)
System.out.println(score + " is a C");
else
System.out.println(score + " is an F");
}
}
Starting with the function letterGrade. Since the function always return false and just prints a sentence, you can replace boolean to void.
Another mistake you did was that if you want to find max and min, the variables shall take the inverse of you want. So the variable max shall take the minimum variable (60) and the maximum value (100).
Finally, in order to change variables max and min you must compare the new value to their current value. This is, to change min value, for example, you have to compare score with current min.
Hope it helps.

Java GPA Program Issue

My program for some reason is calculating the GPA average wrong. If I enter 4.0 three times, then it says the average GPA is 3.0 but should be 4.0. Can someone help me find the issue?
//variables
double gpa = 0;
double total = 0;
int counter = 0;
int counter2 = 0;
do
{
String gpaEntry = JOptionPane.showInputDialog("Please enter GPAs:");
gpa = Double.parseDouble(gpaEntry);
if (gpa >= 3.5)
counter2 ++;
total += gpa;
counter ++;
}
while (gpa != 0);
double average = (double) (total/counter);
JOptionPane.showMessageDialog(null, "The Average GPA is: " + average);
JOptionPane.showMessageDialog(null, "Number of students:" + counter2);
Let's walk through the code
gpa = 0
get user input (user enters '2')
now gpa = 2
total += 2
counter ++
while(gpa != 0) // nope, gpa is 2
loop back
get user input (user enters '0')
now gpa = 0
total += 0
counter ++ // oops!
while(gpa != 0) // yep, quit the loop
but it's too late, we already incremented counter, so our average calculation is wrong
What is wrong is that if a user enters 0, then it runs the program and then exits.
Try this code (Sorry, I do not have an editor at the moment so you might have to fix some small thing).
//variables
double gpa = 0;
double total = 0;
int counter = 0;
int counter2 = 0;
String gpaEntry = JOptionPane.showInputDialog("Please enter GPAs:");
gpa = Double.parseDouble(gpaEntry);
while (gpa != 0) {
if (gpa >= 3.5)
counter2 ++;
total += gpa;
counter ++;
gpaEntry = JOptionPane.showInputDialog("Please enter GPAs:");
gpa = Double.parseDouble(gpaEntry);
}
JOptionPane.showMessageDialog(null, "The Average GPA is: " + average);
JOptionPane.showMessageDialog(null, "Number of students:" + counter2);
Comment if you have any more questions.

Java-Number of scores needs to be one less in answer

So here is my code:
package e7;
import java.util.Scanner;
public class Q1 {
public static void main(String[] args)
{
double[] scores = new double[10];
double sum = 0.0D;
int count = 0;
Scanner sc = new Scanner(System.in);
do {
System.out.print("Enter a new score (-1 to end): ");
scores[count] = sc.nextDouble();
if (scores[count] >= 0.0D)
sum += scores[count];
}
while (scores[(count++)] >= 0.0D);
System.out.println("The total number of scores is: " + count );
double average = sum / (count - 1);
int numOfAbove = 0;
int numOfBelow = 0;
for (int i = 0; i < count - 1; i++) {
if (scores[i] >= average)
numOfAbove++;
else
numOfBelow++;
}
System.out.printf("Average is " + "%.2f\n",average);
System.out.println("Number of scores above or equal to the average " + numOfAbove);
System.out.println("Number of scores below the average " + numOfBelow);
}
}
How do make it display the correct number of scores calculated? If I input 2 numbers and then do the -1 one to end it keeps saying 3 scores. Should only be two. How do I fix this? Thanks
System.out.println("The total number of scores is: " + count );
You probably want:
System.out.println("The total number of scores is: " + (count - 1));
You could also change your loop from a do while to a while loop as follows,
while (true) {
System.out.print("Enter a new score (-1 to end): ");
double tempDouble = sc.nextDouble();
if (tempDouble >= 0.0D)
scores[count] = tempDouble;
sum += scores[count];
count++;
else
break;
}
That way as if your double input isn't correct it would break out of the while loop when the user entered -1. You might have to tweak it a bit for your use case.

Beginner java programming if-else statements inefficient code

My code is correct but it looks too big.I was wondering if it could be more efficient and with even fewer variables.Do you have any hints?Thanks
sample output
Enter three scores: 87 42 94
The lowest score was: 42
The average without the lowest score is: 90.5
The grade is: A
<code>
import java.util.Scanner;
public class GradeAverager
{
public static void main(String[] args)
{
int score1,score2,score3;
double average,average_no_lowest;
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter three scores: ");
score1 = keyboard.nextInt();
score2 = keyboard.nextInt();
score3 = keyboard.nextInt();
average = (score1 + score2 + score3) / 3.0;
System.out.println();
System.out.println("The average is: " + average);
if (score1 < score2 && score1 < score3)
System.out.println("The lowest score was:" + score1);
else if (score2 < score1 && score2 < score3)
System.out.println("The lowest score was:" + score2);
else if (score3 < score1 && score3 < score2)
System.out.println("The lowest score was:" + score3);
if (score1 < score2 && score1 < score3){
average_no_lowest = (score2 + score3)/2.0;
System.out.println("The average without the lowest score is: " + average_no_lowest);
if(average_no_lowest > 90)
System.out.print('A');
else if(average_no_lowest < 90 && average_no_lowest > 80 )
System.out.print('B');
else if(average_no_lowest > 70 && average_no_lowest < 80)
System.out.print('C');
else
System.out.print('D');
}
else if (score2 < score1 && score2 < score3){
average_no_lowest = (score1 + score3)/2.0;
System.out.println("The average without the lowest score is: " + average_no_lowest);
if(average_no_lowest > 90)
System.out.print('A');
else if(average_no_lowest < 90 && average_no_lowest > 80 )
System.out.print('B');
else if(average_no_lowest > 70 && average_no_lowest < 80)
System.out.print('C');
else
System.out.print('D');
}
else if (score3 < score1 && score3 < score2){
average_no_lowest =(score1 + score3)/2.0;
System.out.println("The average without the lowest score is: " + (score1 + score3)/2.0);
if(average_no_lowest > 90)
System.out.print('A');
else if(average_no_lowest < 90 && average_no_lowest > 80 )
System.out.print('B');
else if(average_no_lowest > 70 && average_no_lowest < 80)
System.out.print('C');
else
System.out.print('D');
}
}
}
</code>
Your section of code which reads
if(average_no_lowest > 90)
System.out.print('A');
else if(average_no_lowest < 90 && average_no_lowest > 80 )
System.out.print('B');
else if(average_no_lowest > 70 && average_no_lowest < 80)
System.out.print('C');
else
System.out.print('D');
}
is duplicated 3 times. Put it into a method.
Don't be worried about performance until it is a proven problem. Be worried about how easy it is to read and maintain the code.
Code has 2 audiences - the compiler and humans. Humans matter more than compilers.
Store the lowest score in a variable e.g. lowest_score.
and do the average by (total - lowest_score) / 2
It is the most efficient
You can use the following code,these have fewer lines of code and gives the same output as you want::
public static void main(String[] args) {
int score1, score2, score3, status;
double average, average_no_lowest;
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter three scores: ");
score1 = keyboard.nextInt();
score2 = keyboard.nextInt();
score3 = keyboard.nextInt();
average = (score1 + score2 + score3) / 3;
System.out.println("Average Score was:: " + average);
if (score1 < score2 && score1 < score3) {
status = 1;
System.out.println("The lowest score was:: " + score1);
} else if (score2 < score1 && score2 < score3) {
status = 2;
System.out.println("The lowest score was:: " + score2);
} else {
status = 3;
System.out.println("The lowest score was:: " + score3);
}
if (status == 1) {
average_no_lowest = (score2 + score3) / 2;
System.out.println("The average without the lowest score is: "
+ average_no_lowest);
} else if (status == 2) {
average_no_lowest = (score1 + score3) / 2;
System.out.println("The average without the lowest score is: "
+ average_no_lowest);
} else {
average_no_lowest = (score1 + score2) / 2;
System.out.println("The average without the lowest score is: "
+ average_no_lowest);
}
}

Categories