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

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.

Related

Java Lottery Program Random Number Program

My code below is supposed to take the amount of tickets entered by the user and generate 6 random numbers for each ticket from number 1-49 and then check whether each number is equal or not. This is the output for example when the user enters 6 tickets.
[I#38af3868 [I#77459877 [I#5b2133b1 [I#72ea2f77 [I#33c7353a [I#681a9515
My issue is why are there random letters and symbols with the numbers and why are the numbers generated the same everytime when they are supposed to be different and randomized.
Please guide me or fix my code! Thanks!
Scanner entry=new Scanner(System.in);
int ticketAmnt;
do
{
System.out.println("How many tickets will you be generating?");
ticketAmnt = entry.nextInt();
}
while(ticketAmnt<1 || ticketAmnt>100);
int randomNumbers[] = new int[6];
for (int i = 0; i <randomNumbers.length; i++)
{
randomNumbers[i] = (int) (Math.random() * 50);
}
int lottery [][] = new int [ticketAmnt][randomNumbers.length];
for (int i = 0;i<ticketAmnt;i++)
{
for(int j = 0;j<randomNumbers.length;j++)
{
if (lottery[j] == randomNumbers) // Here, code checks if same random number generated before.
{
int randomNum = (int) (Math.random() * 50); // If random number is same, another number generated.
}
}
}
for (int i = 0; i < lottery.length; i++)
System.out.print(lottery[i] + " ");
Your random number generator for generating the lottery numbers on each ticket is wrong. Your current generator will push out 0 which is not desired in this case. You require numbers inclusively from 1 to 49. If you want to use the Math.random() method then you should perhaps do it this way:
int randomNumber = (int)(Math.random() * 49 + 1);
Don't fall into that trap where you think that adding the 1 to 49 and using 50 to save a math step is going to help you. Math doesn't work that way. Always remember, in an equation, multiplication is always carried out before addition or subtraction.
As already mentioned in comments the string your are seeing (similar to: I#38af3868) is the array object's hashcode which at a glance is pretty much meaningless but there is information there and this hashcode is used for other purposes. The link in comments provided by #tgdavies which is written by #Duncan Jones covers this quite nicely. If you want to display the contents of your let's say randomNumbers[] array to the console window then you can use the java.util.Arrays.toString() method, for example:
System.out.println(java.util.Arrays.toString(randomNumbers);
or you can iterate through the array with something like a for loop and display (or access) the array contents that way, for example:
for (int i = 0; i < randomNumbers.length; i++) {
System.out.println("Array Element at index " + i + " is: --> " + randomNumbers[i]);
}
It would be a little different for your other array, the two dimensional (2D) int array with the variable name of lottery (lottery[][]). A Multi Dimensional Array in Java (like a 2D Array) is an Array of Arrays so you need to sort of treat it as such. Think of a 2D Array as if it were a Table with rows and columns. The outer Array holds the Rows and the inner Array hold the columns for each row. To access the inner arrays (columns) you need to first access the outer (rows) arrays, for example:
for (int row = 0; row < lottery.length; row++) {
for (int column = 0; column < lottery[row].length; column++) {
System.out.println("Element in Row index: " + rows + " Column index: "
+ column + " is: --> " + lottery[row][column]);
}
System.out.println();
}
Consequently for a quick display you can also use the java.util.Arrays.deepToString() method, for example:
System.out.println(java.util.Arrays.deepToString(lottery));
When generating your random numbers for each ticket the are a couple things you obviously need to check for:
When generating a set of 6 numbers make sure no set contains
duplicate numbers. Each number in a set of 6 must be unique within
that set.
When a set of 6 numbers has successfully been generated with unique
numbers make sure that set with the very same numbers has not
already been issued as a ticket. Although the odds of this is very slim...it is
possible.
For the first item, you'll want to do this as the numbers are being generated. A while loop can take care of this business and only allow the code to continue on if in fact all values within the Array are unique, for example:
int haveSix = 0; // Used as an index counter
// If we don't have 6 unique numbers then keep looping until we do.
while (haveSix < 6) {
// Pull a random number from 1 to 49 inclusive.
int randomNum = (int) (Math.random() * 49 + 1);
unique = true; // Assume the generated number is unique
// Check the generated number to see if it's already in the array.
for (int n : randomNumbers) {
if (n == randomNum) {
/* Yup..it's already in the array so unique
goes false and we break out of this loop. */
unique = false;
break;
}
}
/* If the generated number is unique to what is already
in the set then add it to the array. */
if (unique) {
// Add the generated number to the Array.
randomNumbers[haveSix] = randomNum;
haveSix++; // Increment the index counter
}
/* If it's not unique (the unique flag is false) then we loop
again and pull for another random number. We'll keep looping
like this until haveSix = 6 to satisfy the 'while' loop condition.
The haveSix variable will only increment if the random number
is unique to the current array. */
}
At this point you would want to Sort your randomNumbers[] array in ascending order. This serves two purposes, first, it helps when checking ticket sets already contained within the lottery[][] 2D Array against the current set held in the randomNumbers[] array for uniqueness. After all, you don't want to issue two of the same set of numbers. Secondly, it looks nicer when you print out the tickets :)
To sort your randomNumbers[] array in ascending order you can use the java.util.Arrays#sort() method, for example:
java.util.Arrays.sort(randomNumbers);
That's it...sorted. Now all that is required is to ensure that the set of ticket numbers contained within the randomNumbers[] Array is not already in the lottery[][] 2D Array. To do this you will need to iterate through the lottery[][] array and compare the arrays already stored there (if any) with the randomNumbers[] array, for example:
unique = true;
for (int[] ary : lottery) {
// Is the set UNIQUE?
if (Arrays.toString(ary).equals(Arrays.toString(randomNumbers))) {
// Nope... break out and create another new set of ticket numbers
unique = false;
break;
}
}
Notice how the Arrays.toString() method is used to convert all arrays to string so that they can be compared to each other for equality. Now you can see why sorting is important here. If the boolean unique variable (flag) falls to false then the lottery[][] 2D array already contains the same set held in the randomNumbers[] array which is no good. We can't add that set to lottery[][]. We'll need to generate another set of numbers which of course then means, that ticket is not fulfilled and we need to loop again to generate a new set. If it is found the set is unique then it can be added to the lottery[][] 2D Array.
All together, the whole thing would look something like this:
import java.util.Arrays;
import java.util.Scanner;
public class Lotto649 {
public static void main(String[] args) {
Scanner entry = new Scanner(System.in);
int ticketAmnt;
do {
System.out.print("How many tickets will you be generating (1 to 100)? --> ");
ticketAmnt = entry.nextInt();
} while (ticketAmnt < 1 || ticketAmnt > 100);
int[] randomNumbers;
int lottery[][] = new int[ticketAmnt][];
int ticketCount = 0;
boolean unique = false;
while (ticketCount < ticketAmnt) {
randomNumbers = new int[6];
int haveSix = 0;
while (haveSix < 6) {
int randomNum = (int) (Math.random() * 49 + 1);
unique = true;
for (int n : randomNumbers) {
if (n == randomNum) {
unique = false;
break;
}
}
if (unique) {
randomNumbers[haveSix] = randomNum;
haveSix++;
}
}
/* Sort the numbers within the Array in Ascending order.
This helps to check sets of ticket numbers later and,
it looks better when the tickets are printed out. :) */
Arrays.sort(randomNumbers);
/* Array is now ready to add to the lottery[][] array but first
let's make sure the set is uniqie to all other sets already
within the lottery[][] array. */
unique = true;
for (int[] ary : lottery) {
// Is the set UNIQUE?
if (Arrays.toString(ary).equals(Arrays.toString(randomNumbers))) {
// Nope... break out and create another new set of ticket numbers
unique = false;
break;
}
}
if (unique) {
lottery[ticketCount] = randomNumbers;
ticketCount++;
}
}
// Print the lottery tickets to Console Window:
for (int i = 0; i < lottery.length; i++) {
System.out.println("Ticket #" + (i + 1) + ": --> "
+ Arrays.toString(lottery[i]).replaceAll("[\\[\\]]", ""));
}
}
}

Smallest element in largest row

I came across this problem in class and I'm stuck on it. I did plenty of research but I'm not being able to fix my code.
I need to create a matrix and find the smallest value in the row of the largest value (I believe this element is called minimax). I'm trying to do with a simple 3 x 3 matrix. What I have so far:
Scanner val = new Scanner(System.in);
int matrizVal[][] = new int[3][3];
for (int a = 0; a < matrizVal.length; a++) {
for (int b = 0; b < matrizVal.length; b++) {
System.out.print("(" + a + ", " + b + "): ");
matrizVal[a][b] = val.nextInt();
}
}
int largest = matrizVal[0][0];
int largestrow = 0;
int arr[] = new int[2];
for (int row = 0; row < matrizVal.length; row++){
for (int col = 0; col < matrizVal.length; col++){
if (largest < matrizVal[row][col]){
largest = matrizVal[row][col];
largestrow = row;
}
}
}
To find the so called minimax element I decided to create a for each loop and get all the values of largestrow except the largest one.
for (int i : matrizVal[largestrow]){
if (i != largest){
System.out.print(i);
}
}
Here's where I'm stuck! I'd simply like to 'sort' this integer and take the first value and that'd be the minimax. I'm thinking about creating an array of size [matrizVal.length - 1], but not sure if it's gonna work.
I did a lot of research on the subject but nothing seems to help. Any tips are welcome.
(I don't think it is but I apologize if it's a duplicate)
Given the code you have provided, matrizVal[largestrow] should be the row of the matrix that contains the highest valued element.
Given that your task is to extract the smallest value in this array, there are a number of options.
If you want to simply extract the minimum value, a naive approach would go similarly to how you determined the maximum value, just with one less dimension.
For example:
int min = matrizVal[largestrow][0];
for (int i = 0; i < matrizVal.length; i++) {
if (matrizVal[largestrow][i] < min) {
min = matrizVal[largestrow][i];
}
}
// min will be the target value
Alternatively, if you want to sort the array such that the first element of the array is always the smallest, first ensure that you're making a copy of the array so as to avoid mutating the original matrix. Then feel free to use any sorting algorithm of your choice. Arrays.sort() should probably suffice.
You can simplify your approach by scanning each row for the maximum and minimum values in that row and then deciding what to do with those values based on the maximum value found in previous rows. Something like this (untested) should work:
int largestValue = Integer.MIN_VALUE;
int smallestValue = 0; // anything, really
for (int[] row : matrizVal) {
// First find the largest and smallest value for this row
int largestRowValue = Integer.MIN_VALUE;
int smallestRowValue = Integer.MAX_VALUE;
for (int val : row) {
smallestRowValue = Math.min(smallestRowValue, val);
largestRowValue = Math.max(largestRowValue, val);
}
// now check whether we found a new highest value
if (largestRowValue > largestValue) {
largestValue = largestRowValue;
smallestValue = smallestRowValue;
}
}
This doesn't record the row index, since it didn't sound like you needed to find that. If you do, then replace the outer enhanced for loop with a loops that uses an explicit index (as with your current code) and record the index as well.
I wouldn't bother with any sorting, since that (1) destroys the order of the original data (or introduces the expense of making a copy) and (2) has higher complexity than a one-time scan through the data.
You may want to consider a different alternative using Java 8 Stream :
int[] maxRow = Arrays.stream(matrizVal).max(getCompertator()).get();
int minValue = Arrays.stream(maxRow).min().getAsInt();
where getCompertator() is defined by:
private static Comparator<? super int[]> getCompertator() {
return (a1, a2)->
Integer.compare(Arrays.stream(a1).max().getAsInt(),
Arrays.stream(a2).max().getAsInt()) ;
}
Note that it may not give you the (undefined) desired output if two rows include the same highest value .

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

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.

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 do I get an "java.lang.ArrayIndexOutOfBoundsException: 0"

What is wrong here? I get an runtime error when I run the code in Netbeans saying "java.lang.ArrayIndexOutOfBoundsException: 0"
I found out it means something like "the value does not exist" - but that is what I am trying to do - to let the user define the values for the array size. Help, please.
public static void main(String[] args) {
int row = 0;
int colum = 0;
//Declare 2d array
int [][] matrix = new int [row][colum];
//Create input for array size
Scanner input = new Scanner(System.in);
System.out.println("Enter " + matrix[row].length + " rows and " + matrix[colum].length + " colums: ");
for (row = 0; row < matrix.length; row++) {
for (colum = 0; colum < matrix[row].length ; colum++) {
matrix[row][colum] = input.nextInt();
//Input variables to array
//Print the array
for (row = 0; row < matrix.length; row++ ) {
for (colum = 0; colum < matrix[row].length; colum++ ) {
System.out.println(matrix[row][colum] + "");
}
System.out.println();
}
}
}
}
}
Two problems. You need to initialize row and column with non-zero values:
int row = 3;
int colum = 4;
You're not referencing the dimensions of the matrix correctly, you want:
System.out.println("Enter " + matrix.length + " rows and "
+ matrix[0].length + " colums: ");
There are a few more bad references further down. You could of course just use your row and column variables instead of getting the lengths from the matrix though.
For your case
int [][] matrix = new int [0][0];
Means with no element , index starts from 0, where the size you specify starts from 1
Go for ArrayList if you want dynamic array
Your array has 0 elements - you're trying to access the first (with index 0) - which is out of bounds.
You are creating an array of arrays that has size 0 in both dimensions:
int row = 0;
int colum = 0;
//Declare 2d array
int [][] matrix = new int [row][colum];
If you try to index this you will get an ArrayIndexOutOfBoundsException.
Set row and colum to something > 0.
Arrays in Java have a fixed size. Once you have created an array, you can't change the size of it. If you need to change the size at runtime, use a collection class (for example an ArrayList) instead of an array.
int row = 0;
int colum = 0;
int [][] matrix = new int [row][colum];
The declared array has zero rows and zero columns. You can't store anything in it.
The exception occurs here:
matrix[row].length
with row=0 because it is the number of columns of the first row (arrays are zero based!) which doesn't exist.
Your problem is that you're setting row and column to 0, then you create a two-dimensional array of size 0 in both directions, and then this:
matrix[row].length
fails because there is no entry at index 0 - it would require the array to have at least size 1.

Categories

Resources