Getting rid of auto-filled zeroes in 2d Java array - java

The user inputs numbers with a max of 20 per line and 50 lines. The problem is that if the user inputs less than 20 integers on a line, the array is filled with zeros in the empty spaces so that there is 20 total. This impacts my calculations done with the array.
Does anyone know of an efficient way to get rid of those zeros so that only the original inputted numbers remain?
//Extracting/reading from file
public void readFile(File file) {
try {
//creates scanner to read file
Scanner scn = new Scanner(file);
//set initial count (of rows) to zero
int maxrows = 0;
//sets columns to 20 (every row has 20 integers - filled w zeros if not 20 inputted)
int maxcolumns = 20;
// goes through file and counts number of rows to set array parameter for length
while (scn.hasNextLine()) {
maxrows++;
scn.nextLine();
}
// create array of counted size
int[][] array = new int[maxrows][maxcolumns];
//new scanner to reset (read file from beginning again)
Scanner scn2 = new Scanner(file);
//places integers one by one into array
for (int row = 0; row < maxrows; row++) {
Scanner lineScan = new Scanner(scn2.nextLine());
//checks if row has integers
if (lineScan.hasNextInt()) {
for (int column = 0; lineScan.hasNextInt(); column++) {
array[row][column] = Integer.parseInt(lineScan.next());
}
} else System.out.println("ERROR: Row " + (row + 1) + " has no integers.");
}
rawData = array;
}
}

You should look into Lists instead. Since you admit that you don't know how many elements are going to be inserted, we can simply grow out the list with however many things the user wants to add.
// Initialize the initial capacity of your dataMatrix to "maxRows",
// which is NOT a hard restriction on the size of the list
List<List<Integer>> dataMatrix = new ArrayList<>(maxrows);
// When you want to add new elements to that, you must create a new `List` first...
for (int row = 0 ; row < maxrows ; row++) {
if (lineScan.hasNextInt()) {
List<Integer> matrixRow = new ArrayList<>();
for (int column = 0; lineScan.hasNextInt(); column++) {
dataMatrix.add(Integer.parseInt(lineScan.next()));
}
// ...then add the list to your dataMatrix.
dataMatrix.add(matrixRow);
}
}

As mentioned in Java labguage Specifications, all the elements of array will be initialized with '0' value if array is of type int.
However, if you want to differentiate between 0 that is input by user and 0 that is assigned by default, I would recommend using array of Integer class so that all the values are initialized with null, although that would need changing in code (i.e. to check for null value before casting it in int literal), e.g:
Integer[][] array = new Integer[maxrows][maxcolumns];

In that case you cany create ArrayList of ArrayList instead of 2d Arrays.
ArrayList<ArrayList<Integer>> group = new ArrayList<ArrayList<Integer>>(maxrows);
Now you can dynamicaly assign value based on input values, so no extra zero added to data if it contains less than 20 in a row.

I usually use ArrayList<Integer>s when I need a varying number of integers.
If you must have an array, either set everything to -1 (if -1 is an invalid/sentinel input), or count how many times the user inputs numbers. Then you'd just need to stop when you reach the -1, or exceed the number of inputs.

Related

How can I insert a unique value to the next empty index in a 2D array in Java?

I want to have each index of the 2D array to have a unique value for each iteration but my problem is that whenever the user inputs the first value for the first index, it automatically overwrites the remaining empty indexes into the first index value...
String[][] ProductAllData1 = new String[10][6]; // an array that may store 10 unique elements(each element has 6 values)
String[] receivedPInputs = getPInputs(); // gets the values from a function that asks the user to input values
for (int d = 0; d < ProductAllData1.length; d++){
ProductAllData1[d] = receivedPInputs;
System.out.print(Arrays.toString(ProductAllData1[d]));
System.out.println("");
}
Am I missing something to add or is my for loop not correct?
Your responses would be highly appreciated!!
You are assigning the same value to all the indices.
Put the getPInputs() inside the loop!
String[][] ProductAllData1 = new String[10][6];
String[] receivedPInputs;
for (int d = 0; d < ProductAllData1.length; d++) {
receivedPInputs = getPInputs();
ProductAllData1[d] = receivedPInputs;
System.out.print(Arrays.toString(ProductAllData1[d]));
System.out.println("");
}

Java - How to join multiple values in a multidimensional array?

I'm beginner programmer, I have fallen into a rabbit hole trying to understand how to use arrays. I'm trying to create a table using multidimensional arrays and I am looking to create a table with 7 rows and 5 columns.
column 1 = will take values from the user input.This input is stored in an array.
column 2 = will print the highest input in that array.
column 3 = will print the lowest input in that array
column 4 = will print take the increment Total. i.e current input + previous input.
column 5 = will take the increment average. i.e Total/Index
Complete Code below
import java.util.Scanner;
public class Numbers {
public static void main(String[] args)
{
//----User Input - Add values to array ----//
Scanner keyboard = new Scanner(System.in);
int places = 7;
int [] values = new int [places];
int sum = 0;
System.out.println("Enter a Numbers:");
for (int count = 0; count < places; count++)
{
values[count] = keyboard.nextInt();
System.out.println(values[count]);
}
//----------------Total---------------------//
for (int numb : values)
{
sum = sum + numb;
}
System.out.println("\n Total:" + sum);
//----------Average------------------------/
double avg = 0;
if (values.length > 0)
{
avg = sum / values.length;
}
System.out.printf("\n Average:"+ avg);
//---------Table Start---------------------//
int [] [] table = new int [7][5];
for (int row =0; row < 7; row++)
for (int column = 0; column < 5; column++)
table [row][column] = getTable(column, column, column, column, avg);
System.out.println("\n\nIndex\tInput\tHigest\tLowest\tTotal\tAverage");
for (int row = 0; row < 7; row++)
{
System.out.print((row + 1) + " ");
for (int column = 0; column < 5; column++)
System.out.print("\t " + table[row][column] + " ");
System.out.println();
}
}
public static int getTable(int input, int highest, int lowest, int total, double average) {
/* TO DO:
* - add each user input from values array into Input column
*
* - add highest/lowest values in the Highest/Lowest column
*
* - add each of the array element total in Total column - this column should take previous Total plus current total.
* i.e Total = Total + Input
*
* - add Average - Current average value.
*/
return 0;
}
}
What I don't know is how to get my code to fill each of the rows using different values each time.
For Example:
Index 1
1st column take first value of the values array
2nd column: take highest value of the values array
3rd column: take lowest value of the values array
4th column: take previous element of values array plus the current value
5th column: take total/index
I know that may need to create a method to get my program to loop through but I just don't know how to do it. I've tried a few different ways, but I'm just getting confused. In the left corner of the screenshot below, is how the columns would look like. Notice how they are all returning 0, which I known that is coming from the getTable method that I created, which is doing just that.
Basically, in this code, you're looping over all the columns:
for (int row =0; row < 7; row++)
for (int column = 0; column < 5; column++)
table [row][column] = getTable(column, column, column, column, avg);
You don't want to do this. Looping over all the columns would make sense if you were doing pretty much the same thing with each column. But you're not. You want each column to have the result of a very different computation. So it would make more sense to say something like
for (int row = 0; row < table.length; row++) {
table[row][0] = getFirstValue(values);
table[row][1] = getHighestValue(values);
table[row][2] = getLowestValue(values);
...
and so on. (However, I don't really understand how "values" is supposed to be used. You're inputting one set of values, but you're creating a table with 7 rows based on that one set of values. Perhaps there's more things wrong with your code.)
Note a couple of things: (1) I replaced 7 with table.length in the loop. table.length is the number of rows, and will be 7. But if you change things to use a different number of rows, then using table.length means you don't have to change the for loop. (2) My code passes values as a parameter to the different methods, which is necessary because the methods will be making computations on the input values. Your code didn't pass values to getTable(), so there's no way getTable() could have performed any computations, since it didn't have the data.
The code could be improved further. One way would be to define constants in the class like
private static final int FIRST_VALUE_COLUMN = 0;
private static final int HIGHEST_VALUE_COLUMN = 1;
...
table[row][FIRST_VALUE_COLUMN] = getFirstValue(values);
table[row][HIGHEST_VALUE_COLUMN] = getHighestValue(values);
which would be more readable.
A more significant improvement would be not to use a 2-D array at all. Since you have five values with different meanings, the normal approach in Java would be to create a class with five instance variables to hold the computed data:
public class ComputedData {
private int firstValue;
private int highestValue;
private int lowestValue;
public void setFirstValue(int firstValue) {
this.firstValue = firstValue;
}
public int getFirstValue() {
return firstValue;
}
// similarly for other fields
}
table would then be a 1-dimensional array of ComputedData.
This is better because now you don't have to assign meaningless column numbers to different computed values. Instead, the names tell you just what each computed value is. Also, it means you can add new values later that don't have to be int. With an array, all elements in the array have to be the same type (you can use Object which can then hold a value of any type, but that can make the code messier). In fact, you may decide later that the "average" should be a double instead of an int since averages of integers aren't always integers. You can make this change pretty easily by changing the type of an instance variable in the ComputedData class. If you use an array, though, this kind of change gets pretty complicated.

Gets out of bounds exception whenever my column is larger than my rows

I have been beating my head against the wall with my code. I finally got my code to allow me to input whatever numbers the user desires depending on how many rows and columns they want, but for some reason whenever I try to type in a larger column number than row number, I get an error. I've read over my loop tens of times, inserting -1 where I think the program is over counting, but it still won't work. I'm assuming this is the appropriate way to write a multidimensional array when it is completely dependent on the user, but if not, please tell me how to make my code more efficient. Thanks!
public class MultiPractice {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Prompts user to insert desired rows and columns
System.out.print("Enter how many rows you want in your array: ");
int rowSize = input.nextInt();
System.out.print("Enter hwo many columns you want in your array: ");
int colSize = input.nextInt();
// Asks users to insert desired numbers for the multi-array
System.out.print("Enter " + (rowSize*colSize) + " integers: ");
// Creates the multidimensional array
int[][] multi = new int[rowSize][colSize];
// Runs the for loop to put numbers where they belong in array
for (int i = 0; i < multi.length; i++) {
for (int j = 0; j < multi[colSize].length; j++) {
multi[i][j] = input.nextInt();
System.out.print(multi[i][j] + " ");
}
System.out.println();
}
}
}
multi[colSize].length should be multi[0].length or multi[i].length (since you have a rectangular array, these have the same value).
multi[colSize].length is the length of row colSize. Therefore, if you have less than colSize+1 rows (since they start from 0), this is out-of-bounds.
It's .length that's screwing you up here. Multi[colSize].length is not the same as colSize; in fact, it's colSize + 1 (since length starts counting at 1).
My Solution: Instead of using multi.length, you can use i < rowSize. You can also swap out the multi[colSize] with < colSize.

Why does this merge sort give incorrect results?

My assignment is to merge two arrays using int arrays that the user fills and we have to assume that there will be a maximum of 10000 inputs from the user, and the user inputs a negative number to stop. Then sort the array from least to greatest and print it out. Initially i thought that this would be quite easy but when i finished, i began getting outputs such as:
Enter the values for the first array, up to 10000 values, enter a negative number to quit: 1
3
5
-1
Enter the values for the second array, up to 10000 values, enter a negative number to quit
2
4
6
-1
First Array:
1
3
5
Second Array:
2
4
6
Merged Array:
6 1 2 3 4 5
as you can see, the six is out of place and i have no idea how to fix it. Here is the source code, i have included copious comments because I really want you guys to help me out to the best of your abilities. IF it's possible to use the same exact technique without implement new techniques and methods into the code please do so. I know there are methods in java that can do all of this in one line but it's for an assignment at a more basic level.
import java.util.Scanner;
public class Merge
{
public static void main(String [] args)
{
Scanner scan = new Scanner(System.in);
int [] first = new int[10000]; //first array, assume 10k inputs max
int [] second = new int[10000]; //first array, assume 10k inputs max
boolean legal = true; //WILL IMPLIMENT LATER
int end = 0; // set how many elements to put in my "both" array
int end2 = 0;// set how many elements to put in my "both" array
System.out.print("Enter the values for the first array, up to 10000 values, enter a negative number to quit");
//get values
for(int i = 0; i<first.length; i++)
{
first[i] = scan.nextInt(); //fill first with user input
if(first[i] <0) //if negative number, stop loop
{
end = i; //get position of end of user input
break;
}
}
System.out.println("Enter the values for the second array, up to 10000 values, enter a negative number to quit");
for(int i = 0; i<second.length; i++) //exact same as the first get values loop
{
second[i] = scan.nextInt();
if(second[i] <0)
{
end2 = i;
break;
}
}
System.out.print("First Array:\n");
for(int i = 0; i<first.length; i++) //print first array
{
if(i == end) //this prevents from printing thousands of zeros, only prints values that user inputed
break;
System.out.println(first[i] + " ");
}
System.out.print("Second Array:\n");
for(int i = 0; i<second.length; i++) //same as printing first array
{
if(i == end2)
break;
System.out.println(second[i] + " ");
}
int [] both = new int[(end)+(end2)]; //instanciate an int array to hold only inputted values from first[] and second[]
int [] bothF = new int[(end)+(end2)]; //this is for my simple sorter algotithm loop
for(int i = 0; i<both.length; i++) //fill both with the first array that was filled
{
both[i] = first[i];
}
int temp = end; // see below
for(int i = 0;i<both.length; i++) //fill array with the second array that was filled(starting from the end of the first array so that the first set is not overwritten
{
if(temp<both.length){ //this prevents an out of bounds
both[temp] = second[i];
temp++;}
}
//simple sorting algorithm
for(int d = both.length -1;d>=0;d--)
{
for(int i = 0; i<both.length; i++)
{
if(both[d]<both[i])
{
bothF[d] = both[d];
both[d] = both[i];
both[i] = bothF[d];
}
}
}
System.out.println("Merged Array:"); //print the results
for(int i = 0; i<both.length; i++)
{
System.out.print(both[i] + " ");
}
//System.out.println("ERROR: Array not in correct order");
}
Your sorting algorithm is faulty.
It's similar to selection sort, in that you take two elements and swap them if they're out of place. However, you don't stop the comparisons when you should: when the index d is less than the index i, the comparison-and-swap based on arr[d] > arr[i] is no longer valid.
The inner loop should terminate with i=d.
The logic of your sort goes something like this:
On the d-th loop, the elements at d+1 and to the right are correctly sorted (the larger numbers). This is true at the beginning, because there are 0 elements correctly sorted to the right of the right-most element.
On each of the outer loops (with the d counter), compare the d-th largest element slot with every unsorted element, and swap if the other element is larger.
This is sufficient to sort the array, but if you begin to compare the d-th largest element slot with already-sorted elements to its right, you'll end up with a larger number in the slot than should be. Therefore, the inner loop should terminate when it reaches d.
Sure, you can do it like this
for (int i = 0; i < end; i++) {
both[i] = first[i];
}
for (int i = 0; i < end2; i++) {
both[i + end] = second[i];
}
// simple sorting algorithm
for (int d = both.length - 1; d >= 0; d--) {
for (int i = 0; i < d; i++) {
if (both[i] > both[d]) {
int t = both[d];
both[d] = both[i];
both[i] = t;
}
}
}
Output(s) -
Enter the values for the first array, up to 10000 values, enter a negative number to quit3
5
-1
Enter the values for the second array, up to 10000 values, enter a negative number to quit
2
4
6
-1
First Array:
3
5
Second Array:
2
4
6
-1
Merged Array:
2 3 4 5 6
First I will start with some recommendations:
1.Give end1 and end2 the initial value as the array lengths.
The printing part - instead of breaking the loop - loop till i == end(if its not changed by the first part it will stay the array length).
One suggestion is to use a "while" statement on the user input to do the reading part (it seems cleaner then breaking the loop- but its OK to do it like you have done too).
Try to use more functions.
now to the main thing- why not to insert the numbers from both arrays to the join array keeping them sorted?
Guiding:
Keep a marker for each array.
Iterate over the new join array If arr1[marker1]> arr2[marker2]
insert arr2[marker2] to the joint array in the current position.
and add 1 to marker2. and the opposite.
(don't forget to choose what happens if the are equal).
This can be achieved because the arrays were sorted in the first place.
Have fun practicing!
I guess you have sort of a reverse "selection sort"-algorithm going on there. I made an class that run your code and printed out the output after every swap. Here is the code which is the same as you got in your application with the addition of print.
for(int d = both.length -1;d>=0;d--)
{
for(int i = 0; i<both.length; i++)
{
if(both[d]<both[i])
{
int temp = both[d];
both[d] = both[i];
both[i] = temp;
printArray(both);
}
}
}
and when we run this on an example array we get this output
[9, 8, 7, 6]=
-> 6879
-> 6789
-> 6798
-> 6978
-> 9678
The algorithm actually had the correct answer after two swaps but then it started shuffling them into wrong order. The issue is the inner for loops end parameter. When you have run the outer loop once, you can be certain that the biggest number is in the end. 'd' is here 3 and it will swap out a bigger number every time it encounters it. the if clause comparisions in the first loop is 6-9 (swap), 9-8, 9-7, 9-9. All good so far.
Potential problems comes in the second iteration with 'd' as 2. Array is now [6,8,7,9] and comparisons are 7-6, 7-8 (swap with result [6,7,8,9]), 8-8, 8-9 (swap!!) resulting in [6,7,9,8]. the last swap was the problematic one. We knew that the biggest number was already in the last spot, but we still compare against it. with every gotrough of the whole inner loop it will always find the biggest number (and all other bigger than both[d] that is already in place) and swap it to some wrong position.
As we know that the biggest number will be last after one iteration of the outer loop, we shouldn't compare against it in the second iteration. You sort of lock the 9 in the array and only try to sort the rest, being in this case [6,8,7] where d = 3, value 7. hence, your inner loop for(int i = 0; i<both.length; i++) becomes for(int i = 0; i<=d; i++). As an added bonus, you know that in the last iteration i==d, and thus the code inside it, if(both[d]<both[i]) will never be true, and you can further enhance the loop into for(int i = 0; i<d; i++).
In your algorithm you always do four comparisons in the inner loop over four iterations of the outer loop, which means there is a total of 16 comparisons. if we use the i<d we'll just do three comparisons in the inner loop on the first iteration of the outer loop, then two, then one. This brings it to a total of six comparisons.
Sorry if too rambling, just wanted to be thorough.

How to insert a series of elements in an array?

How to insert a series of elements in an array
The current code to insert one element in an array is as follows:
public static void getArrayElement()
{
try
{
if(initialSize==1)
{
//Get the user input
System.out.print("Enter the element: ");
getElement = key.nextInt();
//Assign the user input to the array
for(int i=0; i<index; i++)
{
array[i] = getElement;
}
}
//If the size of the array is not 1 use this
else
{
//Gets the user input
System.out.print("Enter the element: ");
getElement = key.nextInt();
//Create a new empty array with a new size
int[] temp = new int[index];
//Assign the old array into the new array
for(int j = 0; j < index-1; j++)
{
temp[j] = array[j];
}
//Change the size of the old array
array = new int [index];
//Assign the temporary array into the new array with its new size
for(int aSize = 0; aSize< array.length; aSize++)
{
array[aSize] = temp[aSize];
int k = array.length;
array[k-1] = getElement;
}
//Pass the array into sortArray method for sorting
sortArray(array, index);
}
//Increment the index and initialSize
index++;
initialSize++;
}
catch(InputMismatchException e)
{
System.out.println("Invalid Input");
System.exit(0);
}
}
As you see the above code can insert only one element at a time. But if I want to insert a bunch of elements at a time, How do i do that ?
Before finding an answer it is better to understand what arrays are.
Array is a set a of homogeneous elements stored in a contiguous memory
location.
This makes a limitation that Arrays need to know the size when they are initialized to reserve enough space from the memory. This makes insertion not possible at all in the parent array. For that you will have to do an arraycopy or create a new array with a different size.
For example,
int[] array = new int[10]; //Initializes an integer array of size 10.
for(int i=0;i<10;i++){
array[i] = i;
}//stores values from 0 to 9.
Now if you intend to insert one or 'n' elements at the start, you have to either create a new array with size "size of prev array + 1" or "size of prev array + n" respectively. And perform an array copy followed by an insertion at the start.
So, if you want a dynamic object doing this for you (inserting one, inserting in bulk), you will have to define your custom capacity that the array can hold. And then you will have to increase the capacity based on your preference.
Developing on this problem, you will reinvent the Java's ArrayList. So better use it in your case.
If key is a Scanner you could just do this:
while( key.hasNextInt() ) {
int i = key.nextInt();
//do with i whatever you want
}
I'd also suggest using a list instead of an array. Then just pass the list to Collections.sort(list) to keep it sorted.
Although lists only allow you to add objects you could make use of autoboxing and convert an int to Integer upon inserting.
Alternatively there are libraries that support primitive lists out there - Google Guava and Apache Commons, for example, should provide some.
Another alternative might be sorted collections like Apache Common's TreeBag which allows you to add multiple duplicate items into a sorted structure.
You want to copy content of temp into array. You can achieve this in one at most two steps
if (temp.length > array.length)
array = new int[temp.length];
System.arraycopy(temp, 0, array, 0, temp.length) ;

Categories

Resources