Java - 2D arrays, checking for duplication - java

The variable "num" is a 2D array. I'm trying to check in that array, if there are any duplicates. "num" is a user-input.
I have extensively looked through Java documentation and asked my lectures and I can't get a working answer. I understand the concept, what I'm meant to do, but just can't get the coding right.
Here is my code:
for(int i = 0; i < 3; i++){ //3 rows with 5 numbers each
for(int j = 0; j < 5; j++){
num[i][j] = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter value for line: " + i + " and position: "+ j ));
if((num[i][j] == num[i][0]) || (num[i][j] == num[i][1]) ||(num[i][j] == num[i][2]) || (num[i][j] == num[i][3]) || (num[i][j] == num[i][4])){
if(num[i][j] != 0){
num[i][j] = Integer.parseInt(JOptionPane.showInputDialog(null, "ERROR. Enter value for line: " + i + " and position: "+ j ));
}
}
}
}
I have also tried using HashSet, but I think that only works with 1D arrays.
I would like to use something like this, as I feel this I understand the most:
secret = new Random().ints(1, 40).distinct().limit(5).toArray();
But obviously not with Random.
I've tried this:
Set<Integer> check = new HashSet<>();
Random gen = new Random();
for(int i = 0; i < 3; i++){ // 3 rows, 5 numbers
for(int j = 0; j < 5; j++){
num[i][j] = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter value for row " + i + " and position " + j));
check.add(gen.nextInt(num[i][j]));
}
}
This last section of coding (directly above this) compiles and runs, but doesn't check for duplicates.

There are alternative ways to checking for duplicates (e.g. you could loop back through the data you've entered previously into the 2D array in order to check for duplicate values) however here's how I'd go about using a Set to check for duplicates in order to, Are you trying to populate the 2d array with all unique values, where each value is from the user?? (also - knowing this explicitly in the original post would be very helpful, thanks to Michael Markidis for specifying that)
With a little UX knowledge here, separating the ERROR is def helpful to the end-user, as ERROR + re-input at the same time is confusing.
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JOptionPane;
public class App {
public static void main(String[] args) {
int[][] num = new int[3][5];
System.out.println("Before:");
for (int i = 0; i < 3; ++i)
System.out.println(Arrays.toString(num[i]));
Set<Integer> data = new HashSet<Integer>();
for (int i = 0; i < 3; i++) { // 3 rows with 5 numbers each
for (int j = 0; j < 5; j++) {
boolean isGoodInput = false;
while (!isGoodInput) {
String input = JOptionPane.showInputDialog(null, "Enter value for line: " + i + " and position: " + j);
Integer n = Integer.parseInt(input);
if (data.contains(n)) {
JOptionPane.showMessageDialog(null, "ERROR: Try again");
} else {
num[i][j] = n;
isGoodInput = data.add(n);
}
}
}
}
System.out.println("After:");
for (int i = 0; i < 3; ++i)
System.out.println(Arrays.toString(num[i]));
}
}
Note: the 2D array is limited to your specification in the original post as a 3x5, so you'd have to change these values in multiple places to make different sized arrays - perhaps making these more dynamic could speed up further development of this application in the future.

Here's one way to accomplish this where you use the hashset to track what has already been inserted into the 2D array:
int[][] num = new int[3][5];
Set<Integer> check = new HashSet<>();
for (int i = 0; i < 3; i++)
{ // 3 rows, 5 numbers
for (int j = 0; j < 5; j++)
{
int n = 0;
do
{
n = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter value for row " + i + " and position " + j));
} while (!check.add(n)); // keep looping if it was in the hashset
// add it to the array since we know n is not a duplicate at this point
num[i][j] = n;
}
}

Related

not getting correct input for checking for duplicates

for the problem, i am required to take in 10 integers, and then print out the unique numbers. My problem solving approach for this was to scan all the numbers behind the one we are checking to see if there are any duplicates. here's the code I have so far. if i enter in numbers like "1234567891", it only will print "pl: 1" because I add the first number before running the algorithm. Any hypothesis on why it's not working?
//setup
Scanner input = new Scanner(System.in);
String text = input.nextLine();
text = text.replaceAll("\\s",""); //remove all spaces
int[] intDigits = new int[10];
//turn the string into an int array
for (int i = 0; i < 10; i++){
intDigits[i] = text.charAt(i) - '0';
}
input.close();
//add the first number since it will always be unique with my algorithm
String pl = intDigits[0] + " ";
//check every number behind the one we are checking, if all the numbers are not equal to the one we are checking, then add it to the string of unique numbers.
for (int i = 1; i < 10; i++) {
int count = 0;
for (int j = i-1; j >= 0; j--) {
if (intDigits[i] != intDigits[j]) {
count++;
}
}
if (count == i-1) {
pl += intDigits[i];
}
}
System.out.println("\n\npl: " + pl);
The issue is with if (count == i-1). Instead it should be if (count == i).Since you are checking from index 1, count will be 1(j=0) if no duplicate. Similarly, for i=2 count will be 2(j=1,0) if no duplicate. And same for the rest.

Transpose java error

I was trying to do a 2D array program to demonstrate a TRANSPOSE but I am getting error .. here is my code.
import java.util.Scanner;
/* To demonstrate TRANSPOSE USING 2-D array */
public class Array_2ddd {
public static void main(String args[]) {
Scanner s1 = new Scanner(System.in);
int i, j;
int myArray1[][] = new int[9][9];
int myArray2[][] = new int[9][9];
for (i = 0; i < 9; i++) {
for (j = 0; j < 9; j++) {
System.out.println("Enter array from 1 to 9");
myArray1[i][j] = s1.nextInt();
System.out.print("your array is" + myArray2[i][j]);
}
}
// Transposing now...
for (i = 0; i < 9; i++) {
for (j = 0; j < 9; j++) {
myArray2[i][j] = myArray1[j][i];
}
}
// After transposing
for (i = 0; i < 9; i++) {
for (j = 0; j < 9; j++) {
System.out.print("Your array is as follow" + myArray2[i][j]);
}
}
}
}
EDIT: My error during runtime (Solved)
EDIT 2: Solved
EDIT 3: The loop is in infinity ..it keeps on asking for values fromt the user even when i wrote i<9 and j<9..it still keeps on asking for values till infinity..
There are several errors in your code, also it is recommend that the dimensions of the array is to be declared as a final int, so your code works for all matrix sizes and that debugging is easier. In your original code, the errors are:
At the input step, you are printing one element of myArray[2] before you perform the transpose. That means, you are getting your array is0.
In the section commented "After transposing", you are outputting your array wrong. Namely, for each entry, you call System.out.print("Your array is as follow" + myArray2[i][j]);, and that you forgot to add a new line after each row (when inner loop is finished).
"..it keeps on asking for values fromt the user even when i wrote i<9 and j<9..it still keeps on asking for values till infinity.." There are 81 entries for the 9-by-9 case and you did not output which i,j index to be applied. You probably mistaken an infinite loop with a long but terminating loop.
Your transpose step is good.
Here is a refined version of your code which allows you to input array (in reading order, or more technically, row-major order), create a transposed array. You can copy and compare your current code with this code directly to test it.
public static void main(String args[]) {
final int m = 9; // Rows
final int n = 9; // Columns
Scanner s1 = new Scanner(System.in);
int i, j;
int myArray1[][] = new int[m][n]; // Original array, m rows n cols
int myArray2[][] = new int[n][m]; // Transposed array, n rows m cols
// Input
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
// Should be only prompt.
// Improved to show which entry will be affected.
System.out.printf("[%d][%d]" + "Enter array from 1 to 9\n", i, j);
myArray1[i][j] = s1.nextInt();
}
}
// Transposing now (watch for the ordering of m, n in loops)...
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
myArray2[i][j] = myArray1[j][i];
}
}
// After transposing, output
System.out.print("Your array is:\n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
System.out.print(myArray1[i][j] + " ");
}
System.out.println(); // New line after row is finished
}
System.out.print("Your transposed array is:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
System.out.print(myArray2[i][j] + " ");
}
System.out.println();
}
s1.close();
}
For an array with three rows (m = 3) and four columns (n = 4), I inputted the numbers from 0 to 9, and then 0, 1, 2. As expected, the output should be:
Your array is:
0 1 2 3
4 5 6 7
8 9 0 1
Your transposed array is:
0 4 8
1 5 9
2 6 0
3 7 1
You define your matrix as 9x9
int myArray1[][] = new int[9][9];
But actually you want to insert 10x10 items:
for (i = 0; i <= 9; i++)
{
for (j = 0; j <= 9; j++)
So either:
Redefine your arrays to store 10x10 items
int myArray1[][] = new int[10][10];
Only read and store 9x9 items in your defined array
for (i = 0; i < 9; i++) {
for (j = 0; j < 9; j++)
You haven't close your first outer for loop i.e in line 17 and change your array size to 10,as you wanted take 10 input (for 0 to 9 = 10 values).

Receiving an error: variable i is already defined in method main

I am trying to write a program that:
1) asks for user input to create an array of 10 elements
2) checks to make sure the elements are distinct
3) identifies the highest value among the elements.
I think Im close but I keep receiving this error message:
error: variable i is already defined in method main(String[])
for (int i = 0; i < myList.length; i++) {
Here is my full code:
import java.util.Scanner;
public class max101 {
public static void main(String[] args) {
double[] myList = new double[10];
double max = myList[0];
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.print("Enter " + myList.length + " distinct numbers: ");
for (int i = 0; i < myList.length; i++)
myList[i] = input.nextDouble ();
for(int i = 0; i <myList.length; i++) {
for(int j = i+1; j<myList.length; j++) {
if(myList[i] == (myList[j])); {
System.out.println("Numbers are not distinct. Please try again and enter 10 distinct numbers");
}
if(myList[i] != (myList[j])); {
for (int i = 0; i < myList.length; i++) {
if (myList[i] > max) max = myList[i];
System.out.println("The maximum value is " + max);
}
}
}
}
}
}
Try using different variable names in your loops
If you dont want to do the above dont reinitialize the variable with int just put i = 0
It might also be useful to look into how scope works.
My suspicion is you’re not ending your blocks properly — a block meaning from { to }. When I have my IDE indent your code, it is:
for (int i = 0; i < myList.length; i++)
myList[i] = input.nextDouble();
for (int i = 0; i < myList.length; i++) {
for (int j = i + 1; j < myList.length; j++) {
if (myList[i] == (myList[j]))
;
{
System.out.println("Numbers are not distinct. Please try again and enter 10 distinct numbers");
}
if (myList[i] != (myList[j]))
;
{
for (int i = 0; i < myList.length; i++) {
if (myList[i] > max)
max = myList[i];
System.out.println("The maximum value is " + max);
}
}
}
}
I think you see now that i is declared inside a for loop that already declares i. Also once you’ve detected a duplicate I think you should break out of the two loops rather than checking for more duplicates, and not find a max until the user has entered 10 new numbers.
One more tip, don’t put a semicolon after your if ( … ), it breaks your logic.

Numerically listing Arrays

So my code is having a problem. Here's what I want to do: have one array have the original set of numbers (up to 10 numbers) and then copy and paste those numbers onto the second array. And then afterwards, the second area lists those numbers from the first array numerically (going from the lowest number to the highest).
The problem is... my second output is giving me a good output with the lowest numbers going to the highest numbers, however, at the same time, I'm getting a long list of repeated numbers and a ton of zeros if I stop my code with the -9000 input. Can anyone tell me what the problem is and how to fix it? I don't want to sort this second array with the Array.sort() option, by the way. No importing anything but the scanner:
public static void main(String[] args) {
System.out.println("Input up to '10' numbers for current array: ");
int[] array1 = new int[10];
int i;
Scanner scan = new Scanner(System.in);
for (i = 0; i < 10; i++) {
System.out.println("Input a number for " + (i + 1) + ": ");
int input = scan.nextInt();
if (input == -9000) {
break;
} else {
array1[i] = input;
}
}
System.out.println("\n" + "Original Array: ");
for (int j = 0; j < i; j++) {
System.out.println((j + 1) + ": " + array1[j]);
}
System.out.println("\n" + "Organized Array: ");
int[] array2 = new int[i];
for (i = 0; i < array1[i]; i++) {
System.out.println(+array1[i]);
for (int j = 0; j < i; j++) {
int temp;
boolean numerical = false;
while (numerical == false) {
numerical = true;
for (i = 0; i < array1.length - 1; i++) {
if (array2[i] > array2[i + 1]) {
temp = array2[i + 1];
array2[i + 1] = array2[i];
array2[i] = temp;
numerical = false;
}
}
}
}
for (i = 0; i < array2.length; i++) {
System.out.println(array2[i]);
}
}
}
You have several issues that you need to fix to make your program run:
You have forgotten to copy array1 into array2:
The output that you think is coming from sorting array2 is actually from the process of sorting.
int[] array2 = new int[i];
for (int j = 0; j < i; j++) {
array2[j] = array1[j];
}
You placed the output of sorted array inside the loop that does sorting:
Check the level of curly braces, and move the output loop to after the sorting loop
for (i = 0; i < array2.length; i++) {
System.out.println(array2[i]);
}
Your sorting algorithm has an extra loop:
Having the outermost loop makes no sense: your bubblesort algorithm works perfectly without it, so you should remove the loop, and move its body up by one level of nesting:
for (i = 0; i < array1[i]; i++) { // Remove the loop
... // <<== Keep the body
}
Your innermost loop reuses i incorrectly:
Replace loop variable i with another variable, e.g. m
for (int m = 0 ; m < array2.length - 1; m++) {
if (array2[m] > array2[m + 1]) {
temp = array2[m + 1];
array2[m + 1] = array2[m];
array2[m] = temp;
numerical = false;
}
}
Demo.
in your for loop you set i limit to array1[i] value not to array lenght, surely it is wrong.
you are reusing the same index i, inside the other loops of the outer big 'for' loop, so the i value will be messed up by inner loops
you never copied the array1 values to array2

Can't find five lowest values in an array...max works while min array is not assigned values

I'm very close to completing this, all I need is help on finding the five lowest values from a text file by using arrays. I figured out how to find the five highest values, but my min array to find the lowest values always outputs five 0's.
Output: //obviously dependent on individual text file
Total amount of numbers in text file is 10
Sum is: 1832
1775 14 9 9 7 //max
0 0 0 0 0 //min
Any help is much appreciated!
import java.util.Scanner;
import java.io.*;
public class HW3
{
public static void main(String[] args) throws IOException
{
File f = new File("integers.txt");
Scanner fr = new Scanner(f);
int sum = 0;
int count = 0;
int[] max = new int[5];
int[] min = new int[5];
int temp;
while(fr.hasNextInt())
{
count++;
fr.nextInt();
}
Scanner fr2 = new Scanner(new File("integers.txt"));
int numbers[] = new int[count];
for(int i=0;i<count;i++)
{
numbers[i]=fr2.nextInt(); //fills array with the integers
}
for(int j:numbers)//get sum
{
sum+=j;
}
for (int j=0; j < 5; j++) //finds five highest
{
for (int i=0; i < numbers.length; i++)
{
if (numbers[i] > max[j])
{
temp = numbers[i];
numbers[i] = max[j];
max[j] = temp;
}
}
}
for (int j=0; j < 5; j++) //finds five lowest...array not assigned values
{
for (int i=0; i < numbers.length; i++)
{
if (numbers[i] < min[j])
{
temp = numbers[i];
numbers[i] = min[j];
min[j] = temp;
}
}
}
System.out.println("Total amount of numbers in text file is " + count);
System.out.println("Sum is: " + sum);
System.out.println(max[0] + " " + max[1] + " " + max[2] + " " + max[3] + " " + max[4]);
System.out.println(min[0] + " " + min[1] + " " + min[2] + " " + min[3] + " " + min[4]);
}
}
Your min array will be initialized with zero values. So the values in numbers will always be higher (assuming there are no negatives).
I'd suggest that you initialize min[j] with numbers[0] before the inner loop.
for (int j=0; j < 5; j++) //finds five highest
{
min[j] = numbers[0]; // Add this line
for (int i=0; i < numbers.length; i++)
{
Try debugging your code by entering inside your nested min loop the following line:
System.out.println("the value of numbers[i] is: " + numbers[i]);
so it looks like this:
for (int j=0; j < 5; j++) //finds five lowest...array not assigned values
{
for (int i=0; i < numbers.length; i++)
{
if (numbers[i] < min[j])
{
System.out.println("the value of numbers[i] is: " + numbers[i]);
temp = numbers[i];
numbers[i] = min[j];
min[j] = temp;
}
}
}
You'll notice something interesting. The innermost nested part doesn't even start.
Try putting that line into the nested max loop in its respective location instead... and it will run fine and show the max array values. You are getting zero values for the min array because (other than initial assigning) the innermost part of the nested min loop isn't being started somehow, so it fails to run and searched values do not get assigned to the min array.
The outer nested parts of the min loop run fine if you try debugging them with a similar line. It's this part that won't start and something's wrong with:
if (numbers[i] < min[j])
{
System.out.println("the value of numbers[i] is: " + numbers[i]);
temp = numbers[i];
numbers[i] = min[j];
min[j] = temp;
}
(Update)
In the min loop, numbers[i] from i=0 to i=4 have a value of 0 after completing the max loop.
You only need to add one line and use int i=5 instead of int i=0 inside your min loop:
for (int j=0; j < 5; j++) //finds five lowest...array not assigned values
{
min[j] = max[4]; // added line
for (int i=5; i < numbers.length; i++) // change to int i=5
{
if (numbers[i] < min[j])
{...
As the other answer states, your problem is that you did not take into account the arrays beginning at 0. In Java, it sets default values for that data structure. For primitives, this will normally be 0 or false. However, when you move into data structures, you will have problems with null pointer exceptions if you fail to initialize your objects. For this reason, I would urge you to get into the habit of setting the values in your data structures before you ever use them. This will save you A LOT of debugging time in the future.
If you know the values in advance, you can set them manually with {0,0,0,0,0} notation, or your can initialize using a for loop:
for(int i = 0; i < array.length; i++)
array[i] = init_value;
I would recommend that you also look into trying to consolidate as much as possible. For example, in your code you go through the same data 4 times:
1) read the integers from the file into an integer array
2) sum all of the numbers in the integer array
3) look for max
4) look for min
I'm not sure if you've covered functions yet, but one example of consolidating this might look like:
while(fr2.hasNextInt()){
int i = fr2.nextInt();
sum += i;
checkHighest(i);
checkLowest(i);
}
You then define these functions and put the meat elsewhere. This lets you only worry about the loops in one place.
You have 2 problems.
First was explained by Tom Elliott.
The second problem is that also the max[] array is initialized with 0, and when you search for max values you change the value from max array (which is 0) with the value from the numbers array, so the numbers array becomes filled with 0s.
A quick solve (though not the best) would be to copy the numbers array in a temp array and use that temp when searching for min values.
In case you didn't exactly understood what I said, try to make a print of the numbers array after you found the 5 max values.
Just curious , Cant you just sort it(using quick sort) select top five and bottom five ?
- if you can use sorting I think this should work then
int sum = 0;
int count = 0;
int[] max = {Integer.MIN_VALUE,Integer.MIN_VALUE,Integer.MIN_VALUE,Integer.MIN_VALUE,Integer.MIN_VALUE};
int[] min = {Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE};
int temp;
int visited[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (int j : numbers)// get sum
{
sum += j;
}
int tempindex;
for (int j = 0; j < 5; j++) // finds five highest
{
for (int i = 0; i < numbers.length; i++) {
if (visited[i] != 1) {
if (numbers[i] > max[j]) {
max[j] = numbers[i];
tempindex = i;
}
}
}
visited[tempindex] = 1;
}
for (int j = 0; j < 5; j++) // finds five lowest...array not assigned
// values
{
for (int i = 0; i < numbers.length; i++) {
if (visited[i] != 1) {
if (numbers[i] < min[j]) {
min[j] = numbers[i];
tempindex = i;
}
}
}
visited[tempindex] = 1;
}

Categories