Summary function not sorting .csv data entirely - java

I have a .csv that has data that looks like so:
First name Last initial,1/0,1/0,....
It is either a 1 or 0 depending on the persons choice from a txt file that contains 50 pairs of choices.
E.g. Apple
Pear
Dog
Cat
My issue is that my method (classSummary) that keeps count of how many people select the choices only goes halfway and the count is incorrect.
Here is my code as it stands, and any advice would be much appreciated:
public static void classSummary() {
for (Student student : data) {
int[] answers = student.getAnswers();
for (int i = 0; i < answers.length; i++) {
if (answers[i] == 0) {
choices.get(i).setCount(choices.get(i).getCount() + 1);
}

There are two issues in your approach:
You are checking only the case if (answers[i] == 0) you need an else part to handle the case where that is not true, i.e where answers[i] == 1
your answers array is only half the size of your choices list and the ith index in the array holds information about the i * 2 and i * 2 + 1 choices. But at the moment you associate the ith index of answers with the ith index of your choices list.
Change the code in the inner loop of your classSummary method from:
public static void classSummary() {
for (Student student : data) {
int[] answers = student.getAnswers();
for (int i = 0; i < answers.length; i++) {
if (answers[i] == 0) {
choices.get(i).setCount(choices.get(i).getCount() + 1);
}
}
}
}
to
public static void classSummary() {
for (Student student : data) {
int[] answers = student.getAnswers();
for (int i = 0; i < answers.length; i++) {
if (answers[i] == 0) {
choices.get(i * 2).setCount(choices.get(i * 2).getCount() + 1);
} else {
choices.get(i * 2 + 1).setCount(choices.get(i * 2 + 1).getCount() + 1);
}
}
}
}

You could even shorten the code that #Eritrean suggested to:
public static void classSummary() {
for (Student student : data) {
int[] answers = student.getAnswers();
for (int i = 0; i < answers.length; i++) {
int index = i * 2 + answers[i];
choices.get(index).setCount(choices.get(index) + 1);
}
}
}
But you really should validate the inputs of that text file with the answers like:
while (inFile2.hasNextLine()) {
String line = inFile2.nextLine();
String[] x = line.split(",");
String name = x[0];
int[] answers = new int[x.length - 1];
for (int i = 1; i < x.length; i++) {
answers[i - 1] = x[i].trim().equals("0") ? 0 : 1;
}
Student student = new Student(name, answers);
data.add(student);
}
And you could either use a Map<Integer> instead of the ArrayList<Choices> (this means you would not need to implement the whole Choices class). In that case you either use a HashMap if the order of choices does not matter in the result, or a LinkedHashMap if the order of choices shall be kept in the order they appear in the input file.
Or you implement a method increment in your Choices class to improve the readability of your code:
static class Choices {
// ... existing parts go here
void increment() {
count++;
}
}
Instead of choices.get(index).setCount(choices.get(index) + 1); you would then only write choices.get(index).increment();

Related

Number is not added at back of existing array

Learning about Arrays. I am not able to figure out why a new number is not added to the back of my existing array. I read in two textfiles in file_1.txt are the numbers '1 2 3' and in file_2.txt is the number '91'. Basically without the method of Void addBack() the program does what I expect, however by adding the method it seems not make a new Array. Even when I go over the elements[i] = elements[i-1] it won't print it as a whole. I am expecting to print for the first part
The numbers are: 1 2 3 and the second part The numbers are: 1 2 3 91.
public class ExampleLecture {
IntRow readIntRow(Scanner input) {
IntRow result = new IntRow();
while (input.hasNext()) {
result.add(input.nextInt());
}
return result;
}
IntRow setBack(Scanner input) {
IntRow result = new IntRow();
while(input.hasNext()) {
result.addBack(input.nextInt());
System.out.println("here");
}
return result;
}
void print(IntRow row) {
for (int i = 0; i < row.numberOfElements; i++) {
System.out.printf("%d ", row.elements[i]);
}
System.out.printf("\n");
}
void start() {
Scanner in = UIAuxiliaryMethods.askUserForInput().getScanner();
Scanner in2 =UIAuxiliaryMethods.askUserForInput().getScanner();
IntRow row = readIntRow(in);
IntRow row2 = setBack(in2);
System.out.printf("the numbers are: ");
print (row);
System.out.printf("the new numbers are: ");
print (row2);
}
public static void main(String[] args) {
new ExampleLecture().start();
}
}
package examplelecture;
class IntRow {
static final int MAX_NUMBER_OF_ELEMENTS = 250;
int[] elements;
int numberOfElements;
IntRow() {
elements = new int[MAX_NUMBER_OF_ELEMENTS];
numberOfElements = 0;
}
void add(int number) {
elements[numberOfElements] = number;
numberOfElements += 1;
}
void addBack(int number) {
for (int i = numberOfElements; i>0; i--) {
elements[i] = elements[i-1];
elements[i] = number;
}
}
}
You have 2 successive assignments which write to the same position:
elements[i] = elements[i-1];
elements[i] = number;
The value is alway overwritten with number, so the first statement has no effect.
Also in your addBack method your for cycle:
for (int i = numberOfElements; i>0; i--) {
What happens if numberOfElements is 0?
You call it addBack but it looks like a better name for the method is addFirst. Usually index 0 is considered the front, not the back.
First off, both the readIntRow() and setBack() methods create new IntRow objects row and row2. If you want the result to be appended to the first IntRow object created i.e. to row , you should call:
IntRow row = readIntRow(in);
IntRow row2 = row.setBack(in2);
and setBack() needs to be modified to:
IntRow setBack(Scanner input) {
while(input.hasNext()) {
this.add(input.nextInt());
System.out.println("here");
}
return this;
}
Note that in setBack(), if you are trying to append numbers to the end of the IntRow object, you should call add() instead of addBack() as above. If you are trying to add to the front, you should call addBack() [and it might be better to call it addFront() instead].
Also, in the implementation of addBack(), if you are trying to add to the front of the IntRow object, the element[i] = number operation should take place only once, after the loop. Otherwise all the values in indices <= numberOfElements would be overwritten with number.
void addBack(int number) {
for (int i = numberOfElements; i>0; i--) {
elements[i] = elements[i-1];
}
elements[0] = number;
}
Admittedly it is not entirely clear what you are trying to accomplish. But you may have several problems. The first is as follows:
IntRow setBack(Scanner input) {
IntRow result = new IntRow();
while (input.hasNext()) {
result.addBack(input.nextInt());
System.out.println("here");
}
return result;
}
IntRow has nothing in it since it is new. So all you are doing is iterating over the new file which has just 91 in it. Remember, result has no items. So it won't even iterate once in addBack.
So just do the following:
Change your addBack method to just add the numbers. Why use a loop to cascade down the elements since you are doing this within the same instance of IntRow? Just add it on to the end using the numberofElements as the next index.
void addBack(int number) {
elements[numberOfElements++] = number;
}
If you want to copy the contents of one IntRow object to another you would need another method in the IntRow class. Something like:
public void copy(IntRow r) {
for (int i = 0; i < r.numerOfElements; i++) {
elements[i] = r.elements[i];
}
numerOfElements = r.numberOfElements;
}
And keeping with good design it might be better to return numberOfElements in a method such as public int size();

Accessing array of objects from another class

i'm stuck on this code. I'm trying to access an array of objects from another class and compare it in my method.
public static double averageUserscore(GameScore[] scores, int numScores, String name) {
double sum;
int playerScores = 0;
for(int i = 0; i < numScores;) {
if(???? == name) {
sum = sum + scores[i];
playerScores++;
}
}
}
I want to compare [i]th GameScore userName which is in another class to name.
This code should work. To compare Strings in java do not use ==
for(int i = 0; i < numScores;) {
if(scoares[i].getUserName().equals(name)) {
sum = sum + scores[i].getUserScore();
playerScores++;
// maybe break; if only one that should match
}
}

Generic Array List [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 6 years ago.
I need to create an array list using generics. My add method seems to work sometimes, however my get method appears to have a good amount of problems and i don't receive a compile error. However when i try to get an object from the Array list using my get method it throws a java out of bounds exception. here i what i have so far, and i am using BlueJ. Also, the instructions were to set the initial "illusion" length to zero.
public class AL <X> {
private X[]data;
private int count;
public AL() {
count = 0;
data = (X[]) new Object[0];
}
public void add (X v) {
if (data.length != count) {
data[count] = v;
count++;
} else {
X [] newdata = (X[]) new Object[data.length * 2];
for (int i = 0; i < data.length; i++) {
newdata[i] = data [i];
}
count++;
data = newdata;
}
}
public X get(int index) {
if (index >= count || index < 0) {
throw new ICantEven();
} else {
return data[index];
}
}
}
Your add method doesn't work, since the initial backing array you are using has a 0 length, which remains 0 even when you try to double it (since 0*2==0).
You also forgot to actually add the new element when you resize the backing array. If you hadn't forgot that, you'd get the exception in add.
First of all, change the initial size of the array created by your constructor to be positive :
data = (X[]) new Object[10];
Then add
data[count] = v;
to the else clause of your add method (just before count++;).
Your add method can be further simplified :
public AL()
{
count = 0;
data = (X[]) new Object[10];
}
public void add (X v)
{
// resize backing array if necessary
if (data.length == count)
{
X [] newdata = (X[]) new Object[data.length * 2];
for (int i = 0; i < data.length;i++ )
{
newdata[i] = data [i];
}
data = newdata;
}
// add new element
data[count] = v;
count++;
}

Java - Using parallel arrays to find common frequent number/s

I have an array and have already sorted it. I want to be able to find which numbers repeat. Following that, I want to be able to count how many times these numbers repeat. For example in a list [1,2,3,3,4,4] 3 and 4 repeats and they both repeats twice. My following code is able to find which numbers repeats but unable to get my mind around on how to count the number of times they each repeat. And I am using ArrayList. Trying to skip that and keep everything to purely just arrays excluding hashmap too. Appreciate any help. Tnks.
public static void main(String[] args) {
int[] num = {1,2,3,3,4,4};
for(int x : num){
System.out.print(x + " ");
}
System.out.println("\n" + freq(num));
}
public static ArrayList<Integer> freq(int[] num){
ArrayList<Integer> list = new ArrayList<>();
for(int x=0; x < num.length-1; x++){
if(num[x] == num[x+1]){
if(!list.contains(num[x])){
list.add(num[x]);
}
}
}
return list;
}
Well, since your array is sorted,you could use another array where each index corresponds to the amount of hits for this number:
int[] count = new int[num[num.length - 1]];
Then you could increment the index of this counter for each match:
count[num[x] - 1] = count[num[x] - 1] + 1;
This would however not compact your representation, just bring it to another form. Since you do not know the result lenght before the computation, a more compact representation without lists or even better maps is however not possible since the size of an array must be known at creation. This solution will only work with numbers bigger than 0. For other ranges, you have to adjust the offset.
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
int[] num = {1,2,3,3,4,4};
for(int x : num){
System.out.print(x + " ");
}
System.out.println("\n" + freq(num));
}
static class ValueCountPair {
public ValueCountPair( final int val )
{
value = val;
count = 2;
}
public int value;
public int count;
public String toString() {
return "[" + value + ": " + count + "]";
}
}
public static ArrayList<ValueCountPair> freq(final int[] num){
ArrayList<ValueCountPair> list = new ArrayList<ValueCountPair>();
ValueCountPair last = null;
for(int x=0; x < num.length-1; x++){
if(num[x] == num[x+1]){
if ( last == null || last.value != num[x+1] )
list.add( last = new ValueCountPair( num[x+1] ) );
else
++last.count;
}
}
return list;
}
}

First time working with arrays, trying to create frequency table

I can't see where I'm going wrong with this one, I want it to display the frequencies of the survey's result but all I get is zeros, for example if I enter 1,1,2,2,5 I want it to output:
Displaying response frequencies...
1 2
2 2
3 0
4 0
5 1
but instead I get this:
Displaying response frequencies...
1 0
2 0
3 0
4 0
5 0
here is my main method:
import java.util.Scanner;
public class SurveyTester {
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.println("How many people took the survey?");
int numPeople = input.nextInt();
Survey s = new Survey(numPeople);
int nextResponse;
for (int i = 0; i < numPeople; i++)
{
System.out.print("Input the next survey response (values 1-5):");
nextResponse = input.nextInt();
s.addResponse(nextResponse);
}
System.out.println("Displaying all responses...");
s.displayAllResponses();
System.out.println("Displaying response frequencies...");
s.displayResponseFrequencies();
}
}
here is my class:
public class Survey
{
private int numResponses;
private int maxResponses;
private int[] responses;
private int[] frequencies;
private final int NUM_RESPONSES = 5;
public Survey(int nResponses)
{
maxResponses = nResponses;
numResponses = 0;
responses = new int[nResponses];
frequencies = new int[NUM_RESPONSES]; // There are 5 possible responses to the survey
}
public void addResponse(int response)
{
// This method stores the response
// passed in the parameter 'response'
// to the next free space in the array
{
responses[numResponses]= response;
}
numResponses++;
}
public void displayAllResponses()
{
// This method displays on the screen
// all the responses to the survey
for (int i=0; i<maxResponses; i++)
{
System.out.print(responses[i] + " ");
}
System.out.println("");
}
public void calculateResponseFrequencies()
{
// This method calculates the number of
// responses for each possible answer
// to the survey, 1, 2, 3, 4 or 5
// It stores the frequencies in the
// array 'frequencies'
for (int i=1; i<=maxResponses; i++)
{
if (responses[i] == 1)
{
frequencies[1]++;
}
else if (responses[i] == 2)
{
frequencies[2]++;
}
else if (responses[i] == 3)
{
frequencies[3]++;
}
else if (responses[i] == 4)
{
frequencies[4]++;
}
else if (responses[i] == 5)
{
frequencies[5]++;
}
}
}
public void displayResponseFrequencies()
{
// This method displays the response
// frequences for each of the possible
// response, 1, 2, 3, 4 or 5
for (int i=0; i<frequencies.length; i++)
{
System.out.println((i+1) + "\t" + frequencies[i]);
}
}
}
You are not doing anything with your frequencies array. In you your addResponse method, you need to get the appropriate value and increment it. Add a statement like
frequencies[response-1] = frequencies[response-1] + 1;
Note you can do this with 2 arrays, as you are, especially for learning, but a lot of Java developers would use a Map implementation for this sort of thing, where the keys are the entered values and the values are the frequencies. Keeps all the data in one data structure.
public class DuplicatesInArray {
public static void main(String[] args) {
int count = 0;
int[] arr = new int[6];
int[] frequencyArr = new int[6];
arr[0] = 4;
arr[1] = 1;
arr[2] = 1;
arr[3] = 1;
arr[4] = 5;
arr[5] = 4;
for(int i = 0;i < arr.length;i++){
frequencyArr[arr[i]] = frequencyArr[arr[i]] + 1;
}
for(int x = 0;x<frequencyArr.length;x++){
if(frequencyArr[x] > 0){
System.out.println(x + " " + frequencyArr[x] + " times." );
}
}
}
}
Default value in an integer array will be zero. We increment it by one for every occurrence.
Example:If integer 4 occurs 2 times,4th index at the frequencyArr is incremented twice.

Categories

Resources