I have been assigned a task that requires me to utilise a 2D Array. I have to read in a file and export it to a 2D array. I can only have a single method but I am unable to sort the array correctly. I am supposed to sort the data in 3 ways (alphabetically by name and with scores highest to lowest; highest to lowest scores for each student and highest to lowest by the average of 3 scores.) So far I have
import java.util.*;
import java.io.*;
public class ScoreSorter {
public static void main(String[] args) {
int student_num = 30;
String[][] DataInTableArr = new String[30][6];
try {
BufferedReader ReadIn = new BufferedReader(new FileReader("classZ.csv"));
for (int i = 0; i < 30; i++) {
String DataIn = ReadIn.readLine();
String[] DataInArr = DataIn.split(",");
DataInTableArr[i][0] = DataInArr[0];
DataInTableArr[i][1] = DataInArr[1];
DataInTableArr[i][2] = DataInArr[2];
DataInTableArr[i][3] = DataInArr[3];
int temptest1 = Integer.parseInt(DataInArr[1]);
int temptest2 = Integer.parseInt(DataInArr[2]);
int temptest3 = Integer.parseInt(DataInArr[3]);
}
} catch (Exception e) {
System.out.println("Whoops, you messed up, RESTART THE PROGRAM!!!!!");
}
}
}
I have no idea as to how to solve the rest of the task... I would appreciate if someone could tell me of the most efficient way and perhaps an example...
One plausible way is to create a Student class which implements Comparable interface, with the following members:
String name;
int scoreOne;
int scoreTwo;
int scoreThree;
compareTo(Student s) { //implement the comparison following 3 criteria you mentioned }
And, read the files row by row, for each row we create a Student object, and put all rows in a TreeSet. In this way, the TreeSet together with the compareTo method will help us sort the Students automatically.
Finally, iterate the sorted TreeSet to fill up the 2D array.
import java.util.*;
import java.io.*;
public class ScoreSorter {
public static void main(String[] args) {
int student_num = 30;
String[][] DataInTableArr = new String[30][6];
try {
BufferedReader ReadIn = new BufferedReader(new FileReader("classZ.csv"));
for (int i = 0; i < 30; i++) {
String DataIn = ReadIn.readLine();
String[] DataInArr = DataIn.split(",");
DataInTableArr[i][0] = DataInArr[0];
DataInTableArr[i][1] = DataInArr[1];
DataInTableArr[i][2] = DataInArr[2];
DataInTableArr[i][3] = DataInArr[3];
int temptest1 = Integer.parseInt(DataInArr[1]);
int temptest2 = Integer.parseInt(DataInArr[2]);
int temptest3 = Integer.parseInt(DataInArr[3]);
}
/*Code To be Inserted Here*/
} catch (Exception e) {
System.out.println("Whoops, you messed up, RESTART THE PROGRAM!!!!!");
}
}
}
If there are 6 columns such that First is name and the other 3 are scores then what does other 2 columns contain?? I ignore your array declaration :
String[][] DataInTableArr = new String[30][6];
and assume it to be 30x4 array
String[][] DataInTableArr = new String[30][4];
Logic for sorting Alphabetically
if(DataInTableArr[i][0].compareTo(DataInTableArr[i+1][0])){
/* Sorting Name of adjacent rows*/
String temp = DataInTableArr[i][0];
DataInTableArr[i][0] = DataInTableArr[i+1][0];
DataInTableArr[i+1][0] = temp;
/*Sorting the three marks similarly*/
temp = DataInTableArr[i][1];
DataInTableArr[i][1] = DataInTableArr[i+1][1];
DataInTableArr[i+1][1] = temp;
temp = DataInTableArr[i][2];
DataInTableArr[i][2] = DataInTableArr[i+1][2];
DataInTableArr[i+1][2] = temp;
temp = DataInTableArr[i][3];
DataInTableArr[i][3] = DataInTableArr[i+1][3];
DataInTableArr[i+1][3] = temp;
}
Put the above code in bubble sorting algorithm i.e. 2 loops.
Logic for sorting according to highest marks
In this case you have to find the highest marks in all three subjects of each DataInTableArr[i] and then compare the highest marks with that of next row.
Logic for sorting according to Average marks
Calculate the average of each i'th row as
(Integer.parseInt(DataInTableArr[i][1]) + Integer.parseInt(DataInTableArr[i][2]) + Integer.parseInt(DataInTableArr[i][3]))/3
and compare it with [i+1] th rows average.(same formula just replace [i] with [i+1])
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I'm trying to print out the names of the employees and their department and location from a list of the names and id numbers and I keep getting the NullPointerException even though it prints all of the names and locations. It then stops the build and doesn't xecute the print department and print location methods.
I've tried re-doing the for loops and seeing if any one data point was the problem but it seems to happen if I do the loop for all of the Employee objects or if I just do one.
package homework5_parth_desai;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
/**
*
* #author Party Parth
*/
public class Homework5_Parth_Desai {
public static int emplIndex = -1;
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException {
File file = new File("acmeEgr.txt");
Scanner scan = new Scanner(file);
Employee[] emp = new Employee[50];
String s = "";
String t = "";
int r = 0;
while (scan.hasNextLine()) { //scans in file
emplIndex++;
emp[emplIndex] = new Employee();
if (scan.hasNextLine() == true) { //takes first line as first name, second as last naem and third as id number and tehn ccreates an object out of that
s = scan.nextLine();
}
if (scan.hasNextLine() == true) {
t = scan.nextLine();
}
if (scan.hasNextLine() == true) {
r = Integer.parseInt(scan.nextLine());
}
emp[emplIndex].Employee(s, t, r);
// TODO code application logic here
}
printAll(emp);
printDepartment("IT", emp);
printLocation("Auburn Hills", emp);
}
static void printAll(Employee[] ppl) {
for (int i = 0; i < ppl.length; i++) {
System.out.println(ppl[i].toString());
}
}
static void printDepartment(String title, Employee[] ppl) {
for (int i = 0; i < ppl.length; i++) {
if (title.equals(ppl[i].getDept())) {
System.out.println(ppl[i].getName() + " is in " + ppl[i].getLocation());
}
}
}
static void printLocation(String loc, Employee[] ppl) {
for (int i = 0; i < ppl.length; i++) {
if (loc.equals(ppl[i].getLocation())) {
System.out.println(ppl[i].getName() + " is in " + ppl[i].getDept());
}
}
}
}
Small exert of the .txt file:
Alexander
Seiber
10010
Zehua
Showalter
20010
Cassidy
Woodle
20030
Randall
Shaukat
10030
Pam
Korda
10020
Justin
Polito
20030
public static int emplIndex = -1;
Why is the index maintained as a static field? Don't do that.
Employee[] emp = new Employee[50];
The employee array has a fixed size of 50 elements, however
while (scan.hasNextLine()) {
this loop is based on the lines of the acmeEgr.txt file, which might be more than 50.
In that case, you'll get an ArrayOutOfBoundException first
emp[emplIndex] = new Employee();
or a NullPointerException after
emp[emplIndex].Employee(s, t, r);
Instead, if the lines are less then 50, this
for (int i = 0; i < ppl.length; i++) {
System.out.println(ppl[i].toString());
}
will still loop all the 50 elements, because
ppl.length = 50
Thus, this line
ppl[i].toString()
will throw a NullPointerException.
This is what happens if the elements are, for example, 40
System.out.println(ppl[0].toString());
System.out.println(ppl[1].toString());
System.out.println(ppl[2].toString());
System.out.println(ppl[3].toString());
...
System.out.println(ppl[40].toString()); // ppl[40] is null, NullPointerException!
ArrayList is a much easier array type to deal with. Try using it instead of a normal array, because then you don't have to deal with indexes.
I'm trying to create a FileIO where random numbers are placed into a .txt file and outputted, sorted in another .txt file. I have a bubble sort code that can sort numbers & I have another code that makes a .txt file. I'm just not sure how I'd implement these 2 together.
Here's my fileIO code:
public static void main(String[] args) {
File file = new File("test.txt");
//Writes name and age to the file
try {
PrintWriter output = new PrintWriter(file);
output.println("Rober");
output.println(27);
output.close();
} catch (IOException ex) {
System.out.printf("ERROR: %s\n", ex);
}
//Reads from the file
try {
Scanner input = new Scanner(file);
String name = input.nextLine();
int age = input.nextInt();
System.out.printf("Name: %s Age %d\n", name, age);
} catch (FileNotFoundException ex) {
System.out.printf("ERROR: %s\n", ex);
}
}
And here is my bubble sort code:
public static void main(String[] args) {
Random num = new Random();
//Creating an array for 10 integers
int [] number = new int [10];
System.out.print("Random Numbers:");
/*Display the unsorted numbers in a random order.
These numbers range from 0 to 100
*/
for (int d = 0 ; d<number.length ; d++){
/* We add a "+1" to the nextInt(100) here because then the numbers
will only range from 0 to 99.
*/
int RandomG = num.nextInt(100)+1;
number[d] = RandomG;
System.out.print(" " +RandomG);
}
//Display the sorted numbers
System.out.print("\nSorted Numbers:"+Arrays.toString(BubbleSortAsceMethod(number)));
}
public static int [] BubbleSortAsceMethod(int[] number){
int placeholder;
for(int i = 0 ; i < number.length-1 ; i++){
for ( int x = 1 ; x < number.length-i ; x++){
/*If the first number in the sequence is greater than the second
number, than save the first number of sequence in placeholder
and place the second number in the first numbers position, and
put the placeholder in the second numbers position (SWAP).
*/
/*
Since this is saying that when the first term is bigger than the
2nd term, the sequence will increase. If we flip the relational
operator, the sequence will decrease.
*/
if ( number[x-1] < number[x]){
placeholder = number[x-1];
number[x-1] = number[x];
number[x] = placeholder;
}
}
}
return number;
}
I'm kinda new to all this java stuff so please go a bit easy on me! Any help at all is appreciated :)
As the data contained in the file will consist of a pair of values: The name (String) and the age (int), you will need to retain their relationship. The best way of doing this would be to create a Class to represent the data. Eventually you want to sort the data on age using your BubbleSort method. While practically this would not be your first choice to sort data, I assume that this is a requirement. The BubbleSort method you have sorts an int[] by comparing each entry against it's immediate neighbor. With int being primitive, you can directly compare each element using the < operator.
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.age = age;
this.name = name;
}
public String getName() { return name; }
public int getAge() { return age; }
#Override
public String toString() {
return name + System.lineSeperator() + age;
}
#Override
public int compareTo(Person person) {
return this.age - person.age;
}
}
You may want to implement the Comparable interface to compare Objects; in which the interface must be implemented by Overriding the compareTo(Person person) method. You can impose sorting on age by returning the difference in age. This is not the only way you can impose the order you want; you may wish to compare directly using the getAge() of each Object or create a Comparator object.
Using the Comparable interface does allow you to make your BubbleSort class more generic, however (though the array must be of Objects that implement the interface; hence no primitive types).
public class BubbleSort {
public static <T extends Comparable> T[] BubbleSortAsceMethod(T[] array) {
for (int i = 0; i < array.length - 1; i++) {
for (int x = 1; x < array.length - i; x++) {
if (comparator.compare(array[x - 1], array[x]) < 0) {
T placeholder = array[x - 1];
array[x - 1] = array[x];
array[x] = placeholder;
}
}
}
return array;
}
}
You will notice that this sort method has some slight differences from your original, namely the BubbleSortAsceMethod method signature with the introduction of generic type parameters. Once again, this is completely optional, though this does give you the flexibility to use this method in the future for other arrays of Classes that extend the Comparable interface.
If you don't want to use generics or the Comparable interface, you will need to change the method signature and if statement.
You're method signature should instead look like public static Person[] BubbleSortAsceMethod(Person[] array) and the if statement if (array[x-1].getAge() < array[x].getAge())
This can give you an illustration of it working, though this does not consider the file io which should be simple to implement from what you have done already.
static Random random = new Random();
public static void main (String args[]) {
int size = 100;
Person[] peopleArray = new Person[size];
for (int i = 0; i < size; i++) {
String name = generateName(random.nextInt(4) + 4);
int age = random.nextInt(100);
peopleArray[i] = new Person(name, age);
}
peopleArray = BubbleSort.BubbleSortAsceMethod(peopleArray);
}
Note that this conforms, at least as much as possible, to the code you have implemented this far. If the BubbleSort and use of arrays are not critical, data structures that implement the List interface, such as ArrayList, can allow you to implement this much cleaner. This does not use the BubbleSort method at all.
public static void main (String args[]) {
int size = 100;
ArrayList<Person> people = new ArrayList<>();
for (int i = 0; i < size; i++) {
String name = generateName(random.nextInt(4) + 4);
int age = random.nextInt(100);
people.add(new Person(name, age));
}
peopleList.sort(Person::compareTo);
//or, if you don't want to implement comparable
peopleList.sort(Comparator.comparing(Person::getAge));
}
Appendix:
Used for illustrative purposes: Generates a name of a set length (randomly).
static char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
public static String generateName(int length) {
if (length > 0) {
return alphabet[random.nextInt(alphabet.length)] + generateName(length - 1);
}
return "";
}
I am confused with passing ARRAYLIST values from one class to another.
I used the ARRAY in these classes before. I am changed those with ARRAYLISTS.
I have 2 classes. this class has an ARRAYLIST called "locationcells". This programs get 3 random digits from another class and get uses inputs and check if their inputs match the 3 digits. it's more like a guessing game.
import java.util.ArrayList;
class SimpleDotCom {
private ArrayList<String> locationcells;
public void setLocationcells(ArrayList<String> Locs)
{
locationcells = Locs;
}
public String CheckYourself(String StringGuess)
{
String result = " Miss";
int index = locationcells.indexOf(StringGuess);
if (index >= 0)
{
locationcells.remove(index);
if (locationcells.isEmpty())
{
result = "Kill";
}
else
{
result = "Hit";
}
}
return result;
}
}
this looks right.
Now the class with the main method:
import java.util.ArrayList;
class SimpleDotComGame {
public static void main(String[] args)
{
int numOfGuesses = 0;
GameHelper helper = new GameHelper();
SimpleDotCom theDotCom = new SimpleDotCom();
/*
this is the part I don't understand. I used to have the int array and generated random numbers and it worked well.
int randomNum = (int) (Math.random() * 5);
ArrayList<String> locations = new ArrayList<String>();
*/
theDotCom.setLocationcells(locations);
boolean isAlive = true;
while (isAlive == true)
{
String guess = helper.getUserInput("Enter a number");
String result = theDotCom.CheckYourself(guess);
numOfGuesses++;
if (result.equals("Kill"))
{
isAlive = false;
System.out.println("You took " + numOfGuesses + "guesses");
}
}
}
}
If you see the comments section above. That's the part I am getting confused. I used to have an array there. INT array. So I was able to pass the INT random numbers to the "simpledotcom" class. Now it is an arraylist with string type, I am not sure how to move forward.
Thank you all in advance,
int numericGuess = Integer.parseInt(helper.getUserInput("Enter a number"));
Also you can use a list of Integers too:
ArrayList<Integer> locations = new ArrayList<Integer>();
while(//condition){
int randomNum = (int) (Math.random() * 5);
locations.add(randomNum)
}
this way you can perform
locations.indexOf(numericGuess) or locations.contains(numericGuess)
OR
Conversely you can do,
String guess = helper.getUserInput("Enter a number");
ArrayList<String> locations = new ArrayList<String>();
while(//condition){
int randomNum = (int) (Math.random() * 5);
locations.add(String.valueOf(randomNum))
}
and check by
locations.indexOf(guess) or locations.contains(guess)
You can always transform the random int to a string by using Integer.toString() before inserting into your array list.
You can convert the String back to int using Integer.parseInt()
E.g.
for (int i = 0 ; i < 3 ; i++)
{
locations.add(Integer.toString((int)(Math.random() * 5));
}
If I understand well: add 3 Strings to the ArrayList:
ArrayList<String> locations = new ArrayList<String>();
for (i=0; i<3; i++)
{ locations.add(String.valueOf((int) (Math.random() * 5))); }
Anyway, you might refactor a little as well, starting with the extracting the above lines from the main method.
Another way might be to store your integer in a list, and convert the guesses to integers. Looks more logic to me anyway. In that case, you'll have an ArrayList. To convert a string to an integer:
int guessNumber = Integer.parseInt(guess);
or
Integer guessNumber = Integer.valueOf(guess);
Both will throw a NumberFormatException if 'guess' does not contain a parseble integer (see javadoc )
Why are you not using arrays like (apparently) you did before, by the way?
I am having a problem in this code. what i am trying to do is read a file and store a studentID and score into an array of scores into the scores property of a student object, but I keep getting the last scores only when I print. Here is the code. can you tell me if my setter property is a correct way of assigning an array in the student class? the problem is the last line of the score file is stored in every array even though when I debug it I see the score array being passed and the studentID array works fine.
import lab6.*;//importing the necessary classes
public class Main
{
public static void main(String[] args)
{
Student lab6 [] = new Student[40];
//Populate the student array
lab6 = Util.readFile("studentScores.txt", lab6);
lab6[4].printStudent();
}
}
The student class------------------------------------
package lab6;
public class Student
{
private int SID;
private int scores[] = new int[5];
//write public get and set methods for SID and scores
public int getSID()
{
return SID;
}
public void setSID(int SID)
{
this.SID = SID;
}
public int[] getScores()
{
return scores;
}
public void setScores(int scores[])
{
this.scores = scores;
}
//add methods to print values of instance variables.
public void printStudent()
{
System.out.print(SID);
System.out.printf("\t");
for(int i = 0; i < scores.length; i++)
{
System.out.printf("%d\t", scores[i]);
}
}
}
the util class --------------------------------------------------------------------
import java.io.*;
import java.util.StringTokenizer;
//Reads the file and builds student array.
//Open the file using FileReader Object.
//In a loop read a line using readLine method.
//Tokenize each line using StringTokenizer Object
//Each token is converted from String to Integer using parseInt method
//Value is then saved in the right property of Student Object.
public class Util
{
public static Student [] readFile(String filename, Student [] stu)
{
try {
String line[] = new String[40];//one line of the file to be stored in here
StringTokenizer stringToken;
int studentID;//for storing the student id
int[] studentScoreArray = new int[5];//for storing the student score
FileReader file = new FileReader(filename);
BufferedReader buff = new BufferedReader(file);
boolean eof = false;
int i = 0;
buff.readLine();//used this to skip the first line
while (!eof) //operation of one line
{
line[i] = buff.readLine();
if (line[i] == null)
eof = true;
else //tokenize and store
{
stringToken = new StringTokenizer(line[i]);
String tokenID = stringToken.nextToken().toString();//for storing the student id
studentID = Integer.parseInt(tokenID);
stu[i] = new Student();//creating student objects
stu[i].setSID(studentID);//stored in student object
//now storing the score-------------------------------------------------
int quizNumberCounter = 0;
while (stringToken.hasMoreTokens())
{
String tokens = stringToken.nextToken().toString();
studentScoreArray[quizNumberCounter] = Integer.parseInt(tokens);//converting and storing the scores in an array
quizNumberCounter++;//array progression
}
stu[i].setScores(studentScoreArray);//setting the score(passing it as an array)
//-----------------------------------------------------------------------
}
i++;
}
buff.close();
} catch (IOException e) {
System.out.println("Error -- " + e.toString());
}
return stu;
}
/*
StringTokenizer st = new StringTokenizer("this is a test");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
//How to convert a String to an Integer
int x = Integer.parseInt(String) ;*/
}
Sample file Structure -------------------------------------------------------
4532 011 017 081 032 077
The issue lies within the line
int[] studentScoreArray = new int[5];
You'll have to move this one inside your student loop and initialize the array per student. Otherwise you are reusing the same array (i.e. memory) for all students and you are overwriting scores over and over again.
// int[] studentScoreArray = new int[5]; // <= line removed here!!!
...
while (!eof) //operation of one line
{
line[i] = buff.readLine();
if (line[i] == null)
eof = true;
else //tokenize and store
{
int[] studentScoreArray = new int[5]; // <= line moved over to here!!!
...
}
}
I havent tested the code with my suggestion, but take a look at:
int[] studentScoreArray = new int[5];
You create this once and once only for the whole file.
A simple and easy fix is to do it for every new line read instead.
like this :
int[] studentScoreArray = new int[5];
int quizNumberCounter = 0;
while(..) { ...}
One reason you may only being seeing one line of results is that you are only printing one line of results:
lab6[4].printStudent();
You will need to change this to loop through the array if you want to see all the results:
foreach (Student student : lab6)
{
student.printStudent();
}
On a side note, your array should probably be called something like students instead of lab6. Also it is idiomatic in java to declare arrays using Type[] identifier rather than Type identifier [].
DISCLAIMER: There may be other stuff wrong, I didn't read all the hundreds of lines posted!
import java.io.*;
import java.util.*;
class StepfordHouses {
private ArrayList<Integer> houses; // A list containing houses
private TreeSet<Integer> ordered; // An ordered treeset of houses
private TreeSet<Integer> processed; // Elements already processed
private String inpline[]; // An array of String holing houses heights in physical order
private int disorientedindex; // The index for the Street
private int size; // Number of houses in the Street
public StepfordHouses() // Constructor for init
{
houses = new ArrayList<Integer>();
ordered = new TreeSet<Integer>();
processed = new TreeSet<Integer>();
// Basic Input from Text-File (Codechef Requirment)
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
size = Integer.parseInt(br.readLine());
inpline = br.readLine().split(" ");
} catch (IOException e) {
System.out.println("BAAAAAAAAAM!!");
}
for (int c = 0; c < size; c++) // Populating Houses
{
Integer tmp = Integer.parseInt(inpline[c]);
houses.add(tmp);
ordered.add(tmp);
}
}
public int calcIndex()
{
int c = 0;
while (c < size) {
Iterator<Integer> it = ordered.iterator();
Integer h1 = houses.get(c); // Get an element from the raw ArrayList of Houses
Integer h = it.next(); // Get an element from the Iterator
while (h1.equals(h) != true) {
if (processed.contains(h1) == false) { // The element is not already processed
System.out.println(h1 + " " + h);
disorientedindex++;
}
h = it.next(); // Get an element from the Iterator
}
processed.add(h1);
c++;
it = null;
}
return disorientedindex;
}
}
public class Work {
public static void main(String args[]) {
StepfordHouses sh = new StepfordHouses();
System.out.println(sh.calcIndex());
}
}
The contains() method doesn't work the way I expect it to, i.e compare Integers!
The output is 15 , which should be 9 when
if(processed.contains(h1)==false) works correctly and returns true when an element is already present!
Where could the code be wrong?
The logic is flawed. processed.add(h1); is called N times but processed.contains(h1) is called N*N times. So depending on the input you can have disorientedindex <> N.