I am having difficulty figuring out where I've gone wrong in this program. It will give me the lowest score and the third lowest score, but not the second lowest score.
I am also at a loss for how to make the program accept first name only or first and last name. I know how to do one name or two, but not either or.
Any help is greatly appreciated!
(Find the three lowest scores) Write a program that prompts the user to enter the number of students and each student’s name and score, and finally displays the student with the lowest score and the student with the second-lowest score and the student with the third lowest score.
Program must accept first name only or first and last name
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//variables
String name1 = "";
String name2 = "";
String lowestName1 = "";
String lowestName2 = "";
String lowestName3 = "";
double score = 0.0;
double lowestScore1 = -1.0;
double lowestScore2 = -1.0;
double lowestScore3 = -1.0;
int numStudent = 0;
int i = 1; //counter
//get number of students
System.out.print("Enter the number of students: ");
numStudent = input.nextInt();
for (i = 1; i <= numStudent; i ) {
System.out.println("Student " i " of " numStudent);
System.out.print("Enter student's name: ");
name1 = input.next();
//name2 = input.next();
System.out.print("Enter student's score: ");
score = input.nextDouble();
if (i == 1) {
lowestScore1 = score;
lowestName1 = name1;
}
if (score < lowestScore1) {
lowestScore1 = lowestScore2;
lowestName1 = lowestName2;
lowestScore1 = score;
lowestName1 = name1;
} else {
lowestScore2 = score;
lowestName2 = name1;
}
if (score > lowestScore1 && score < lowestScore2){
lowestScore3 = lowestScore2;
lowestScore2 = score;
}
if (score < lowestScore2) {
lowestScore3 = lowestScore2;
lowestName3 = lowestName2;
lowestScore2 = score;
lowestName2 = name1;
} else {
lowestScore3 = score;
lowestName3 = name1;
}
}
System.out.println("The lowest score was " lowestScore1 " and " lowestName1 " got it");
System.out.println("The second lowest score was " lowestScore2 " and " lowestName2 " got it");
System.out.println("The third lowest score was " lowestScore3 " and " lowestName3 " got it");
}
}
CodePudding user response:
The following code should work (I will explain everything below):
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("First student name: ");
String name1 = input.nextLine();
boolean firstOnly = true;
if(name1.indexOf(" ") != -1){
firstOnly = false;
}
System.out.println("First student score: ");
double score1 = input.nextDouble();
System.out.println("Second student name: ");
input.nextLine();
String name2 = input.nextLine();
if(firstOnly){
while(name2.indexOf(" ") != -1){
System.out.println("Please enter first name only");
name2 = input.nextLine();
}
}
else{
while(name2.indexOf(" ") == -1){
System.out.println("Please enter first and last name");
name2 = input.nextLine();
}
}
System.out.println("Second student score: ");
double score2 = input.nextDouble();
input.nextLine();
System.out.println("Third student name: ");
String name3 = input.nextLine();
if(firstOnly){
while(name3.indexOf(" ") != -1){
System.out.println("Please enter first name only");
name3 = input.nextLine();
}
}
else{
while(name3.indexOf(" ") == -1){
System.out.println("Please enter first and last name");
name3 = input.nextLine();
}
}
System.out.println("Third student score: ");
double score3 = input.nextDouble();
input.close();
String[] names = {name1,name2,name3};
double[] scores = {score1,score2,score3};
for (int i = 0; i < 2; i ){
double min = scores[i];
int minInd = i;
for (int j = 1; j < 3; j ){
if (scores[j] < min){
min = scores[j];
minInd = j;
}
}
double tempScore = scores[minInd];
scores[minInd] = scores[i];
scores[i] = tempScore;
String tempName = names[minInd];
names[minInd] = names[i];
names[i] = tempName;
}
for (int i = 0; i < 3; i ){
System.out.println(names[i] ": " scores[i]);
}
}
}
Yeah..it is a lot.
OKAY SO the first part is just taking in user input: the names and scores. I also implemented the "either only first names or both first and last names only" feature.
The way I did that was to first take in user input for the first name. I created a boolean variable, firstOnly
, that stores if the names should either be first names or not. If the value of name1
contains a space, then we set this to false, otherwise it is true.
When we take user inputs for name2
and name3
, if firstOnly
is true, then we will keep asking for user inputs until their input contains no space. If firstOnly
is false, then we will keep asking for user inputs until their input contains a space.
Make sure that when you take in user input for the test scores, you type in input.nextLine()
afterwards. This is because after you enter an int
or double
into user input, it will leave behind a trailing newline which will affect the following user input if it is a String.
Next, we store the 3 names and 3 scores in lists: names
, scores
. Now, we need to sort the lists with respect to scores
. That is, we sort scores
and shuffle names
the same way so that the elements correspond to each other.
To sort scores
we can use selection sort. I will quickly explain selection sort below:
Let's say we have an array, arr
that has 4 elements. We find the minimum element from arr[0]
to arr[3]
. After we find this minimum element, we swap it with arr[0]
.
Next, we continue to find the minimum element from arr[1]
to arr[3]
and swap it with arr[1]
. We continue this process until we reach the end of our loops.
The key to this problem is to modify the "swapping" part of selection sort. By applying the same changes of scores
to names
the arrays elements will maintain the correspondence to each other prior to the sorting.
Here is a kind of "test" that may help demonstrate:
names = {"Apple", "Banana", "Carrot", "Date"};
scores = {50, 20, 40, 60};
We set our swapping element to scores[0]
, 50
and find the minimum between {50,20,40,60}
, which is 20
. We then switch 50
and 20
, and thus we switch "Apple"
and "Banana"
.
Now we have:
names = {"Banana", "Apple", "Carrot", "Date"};
scores = {20, 50, 40, 60};
We set our swapping element to scores[1]
, 50
and find the minimum between {50,40,60}
, which is 40
. We then switch 50
and 40
, and thus we switch "Apple"
and "Carrot"
.
names = {"Banana", "Carrot", "Apple", "Date"};
scores = {20, 40, 50, 60};
We set our swapping element to scores[2]
, 50
and find the minimum between {50,60}
, which is 50
. We then switch 50
and 50
, and thus we switch "Apple"
and "Apple"
, which has no change.
Thus, our final arrays are:
names = {"Banana", "Carrot", "Apple", "Date"};
scores = {20, 40, 50, 60};
Now we can print them out and they will be outputted from least to greatest (in our problem we can only have 3 names and 3 scores but it's the same idea).
I hope this helped answer your question! Please let me know if you need any further clarification or details :)
CodePudding user response:
Existing code has some logical flaws in the structure of if-else
statements and the typos when reassigning the lowest score values.
The comparison should start from the minimal score and "shift up" previous scores: first the current score is compared to lowestScore1
, then to lowestScore2
and finally to lowestScore3
:
for (i = 1; i <= numStudent; i ) {
System.out.println("Student " i " of " numStudent);
System.out.print("Enter student's name: ");
name1 = input.next();
System.out.print("Enter student's score: ");
score = input.nextDouble();
if (i == 1) {
lowestScore1 = score;
lowestName1 = name1;
}
if (score < lowestScore1) { // new minimum found
lowestScore3 = lowestScore2; // shifting up 2nd to 3rd
lowestName3 = lowestName2;
lowestScore2 = lowestScore1; // shifting up previous min to 2nd
lowestName2 = lowestName1;
lowestScore1 = score; // storing current minimum
lowestName1 = name1;
} else if (score < lowestScore2) { // new 2nd minimum found
lowestScore3 = lowestScore2; // shifting up 2nd to 3rd
lowestName3 = lowestName2;
lowestScore2 = score; // storing current 2nd minimum
lowestName2 = name1;
} else if (score < lowestScore3) {
lowestScore3 = score; // storing current 3rd minimum
lowestName3 = name1;
}
}
However, this works fine only if all the students have different scores.
If the scores are repeated then several students may share the same score and therefore some collection of the students per score may be required.