check if two rows or columns of a matrix are equal - java

I'm trying to check if two columns of a square matrix are equal. The function is working, but I want to reduce the complexity by using two for instead of three. It's possible? I tried a lot and I couldn't.
int a=0;
boolean equalColumns=false;
for(int k=0;k<this.getRows()-1;k++){
for(int i=k;i<this.getRows()-1;i++){
for(int j=0;j<this.getColumns();j++){
if(this.getElement(j, k)==this.getElement(j, i+1)){
a++;
}
}
if(a==this.getColumns()){
equalColumns=true;
}
}
}

Maybe I didn't understand completely your question; if you have a nXn matrix called M and you want to check if col1 and col2 are equals you can do this:
for(int row = 0; row<M.lenght;row++)
if (M[row][col1] != M[row][col2]) return false;
return true;

I would write a method to check on two columns.
this uses two loops to check each column against the others.
if any return true, the loop short circuits and displays the result.
int n = 8;
boolean result = false;
int[][] mat = new int[n][n];
outer: for (int c1 = 0; c1 < n - 1; c1++) {
for (int c2 = c1 + 1; c2 < n; c2++) {
if (result = equalColumns(mat, c1, c2)) {
break outer;
}
}
}
if (result) {
System.out.println("contains equal columns");
}
this just takes the matrix and the columns to be checked and compares them.
it also short circuits as soon as a mismatch is found.
public static boolean equalColumns(int[][] mat, int cola,
int colb) {
for (int row = 0; row < mat.length; row++) {
if (mat[row][cola] != mat[row][colb]) {
return false;
}
}
return true;
}

Related

difference between returning true and false statements at the end in a boolean method Java

Good day. I got a slight confusion with the true\false return calls in a boolean method.
So the code is :
public class CheckOut {
public static void main(String[] args) {
int[][] m = new int[3][3];
int[][] m1 = new int[m.length][m[0].length];
System.out.println("Enter the nums for the first matrix : ");
getM(m);
System.out.println("Enter the nums for the second matrix : ");
getM(m1);
System.out.println(strictlyIdentical(m, m1));
}
static int[][] getM(int[][] m) {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
m[i][j] = sc.nextInt();
}
}
return m;
}
static boolean strictlyIdentical(int[][] m, int[][] b) {
if (m.length != b.length && m[0].length != b[0].length) {
return false;
}
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
if (m[i][j] != b[i][j]) {
return false;
}
}
}
return true;
}
}
The above method works totally fine and returns true if two matrices are identical but
why when I compare the values on their correctness and return true if the vals in the if statements are correct and return false at the end i don't get the desired output .(it is literally true for any entered nums)
Consider this:
static boolean strictlyIdentical(int[][] m, int[][] b) {
if (m.length == b.length && m[0].length == b[0].length) {
return true;
}
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
if (m[i][j] == b[i][j]) {
return true;
}
}
}
return false;
}
}
Now I'm comparing the values on their similarity not difference , if i can say so...
And the output of this code if given the following input is as follows:
Enter the nums for the first matrix :
12 3 4 3 2 1 2 3 3
Enter the nums for the second matrix :
1 2 3 2 3 2 1 2 3
true
So the preceding method returns true whereas the nums are apparently different.
But the logic didn't change in my opinion...
is there a certain rule that dictates the order of return statements?
or is there a logic issue in my code?
So im not sure if you just looked at your code too long and didnt see this little line of code, but it always return true because of the first if statement.
static boolean strictlyIdentical(int[][] m, int[][] b) {
if (m.length == b.length && m[0].length == b[0].length) {
return true;
}
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
if (m[i][j] == b[i][j]) {
return true;
}
}
}
return false;
}
The first if statement will always return true if the lengths are equal. The example you gave had matrices with the same length, and therefore returned true.
EDIT*****
Your for statement also will return true on the FIRST match between the matrices. Lookinbg at the if statement, the first index where the 2 matrices are equal, the return causes the code to break out of the function and return true, not considering other cases after the first similarity. After any return statement is called, the function is abandoned and will no longer do any code after the return statement is called.
The second implementation definitely has a logic error. The difference is that the first will return false if any two elements are not equal while the second will return true as soon as any two elements are equal, not to mention, the first check is also wrong as JakeTheSnake indicated.
Obviously, in your case, you have to go through every position in both matrices and be sure that each is equal - that's why the the first implementation works, and the second does not.
When you use return inside a method, it automatically ends the execution of that method.
So think about it, at the first two lines you tell your method to return true if only the sizes of the two matrices are identical. So in the example you gave, it's enough that the two matrices are the same size to get true.
The same thing happens when you get to the for loops afterward, it is enough to have one identical value at the same index to return true.
This is why you should check whether they are not identical, and then return false. And only if they "passed" all examinations, then you can return true.
Your piece of code can't work for many reasons, e.g. why does your function return True if the matrices have the same amount of row and the first rows have the same amount of values?
if (m.length == b.length && m[0].length == b[0].length) {
return true;
}
You don't check the values inside the rows!
By the way I write down my solution, try this and if you have questions I'm here to respond.
static boolean strictlyIdentical(int[][] m, int[][] b) {
// Check if both matrices have the same amount of row, if not then return false
if (m.length == b.length) {
// If yes save that number
int rowAmount = m.length;
// Start control the i-th row
for (int i = 0; i < rowAmount; i++) {
// Check if the i-th row of both matrices have the same amount of values, if not then return false
if(m[i].length != b[i].length) return false;
// If yes save that number
int rowLength = m[i].length;
// Check if values are equal, if not then return false
for (int j = 0; j < rowLength; j++) {
if (!(m[i][j] == b[i][j])) return false;
}
}
// Matrices passed all controls, they are IDENTICAL
return true;
}
return false;

Java Program to Determine if there are any Duplicate Rows in the Matrix of a 2-Dimensional Array?

So, as the title says, I'm trying to put together a program that will compare the rows of a 2-dimensional array and determine if any rows are identical.
This has to be accomplished in two parts; determining whether any rows are identical and determining how many rows are identical. I'm trying to use a Boolean method to determine whether there are any identical rows and a separate method to determine how many rows are identical if the Boolean method returns true.
For example, if the array were:
1 2 3
2 3 1
1 2 3
Then the Boolean method would return true and the output would be:
The matrix has 2 identical rows.
The issue is that I don't know how I should set up the Boolean method; if I could figure that much out, the rest of the program would be simple to figure out.
How can I set up the Boolean method for this?
Here's the code I've come up with so far if anyone needs it:
public class IdenticalRows {
public static void main(String[] args) {
Scanner KBin = new Scanner(System.in);
char run;
int ROW, COL;
System.out.println("Would you like to begin? (Y/N)");
run = KBin.next().charAt(0);
do {
if(run!='y' && run!='Y' && run!='n' && run!='N') {
System.out.println("Please only type 'y' or 'Y' to begin or type 'n' or 'N' to close the program.");
System.out.println("Would you like to begin? (Y/N)");
run = KBin.next().charAt(0);
}
}while(run!='y' && run!='Y' && run!='n' && run!='N');
do {
System.out.println("Please enter the number of rows:");
ROW = KBin.nextInt();
do {
if (ROW<=0) {
System.out.println("Entry invalid; must be a positive integer greater than 0.");
System.out.println("Please enter the number of rows:");
ROW = KBin.nextInt();
}
}while(ROW<=0);
System.out.println("Please enter the number of columns:");
COL = KBin.nextInt();
do {
if (COL<=0) {
System.out.println("Entry invalid; must be a positive integer greater than 0.");
System.out.println("Please enter the number of columns:");
COL = KBin.nextInt();
}
}while(COL<=0);
int[][] testDuplicates = new int[ROW][COL];
randArray (testDuplicates, MIN, MAX);
System.out.println("Thematrix is:");
printArray(testDuplicates);
System.out.println(" ");
boolean presence = duplicates(testDuplicates);
if (presence=true) {
countDuplicates(testDuplicates);
}
else if (presence=false) {
System.out.println("There are no identical rows in this matrix.");
}
System.out.println("Would you like to run the program again? (Y/N)");
run = KBin.next().charAt(0);
}while(run=='y' || run=='Y');
}
public static void randArray(int[][] matrix, int low, int up) {//Establishes the values of the elements of the array
Random rand = new Random();
for (int r = 0; r < matrix.length; r++) {
for (int c = 0; c < matrix[r].length; c++) {
matrix[r][c] = rand.nextInt(up-low+1)+low;
}
}
}
public static void printArray(int[][] matrix) {//Prints the elements of the array in a square matrix
for (int r = 0; r < matrix.length; r++) {
for (int c = 0; c < matrix[r].length; c++) {
System.out.printf("%5d",matrix[r][c]);
}
System.out.println(" ");
}
}
public static boolean duplicates(int[][] list) {//Determines if any row(s) of elements ever repeat
for (int r=0; r<list.length; r++) {
for (int c=0; c<list[r].length; c++) {
}
}
return false;
}
public static void countDuplicates(int[][] matrix) {
for (int r=0; r<matrix.length; r++) {
for (int c=0; c<matrix[r].length; c++) {
}
}
}
public static final int MAX=3;
public static final int MIN=1;
}
Thank you in advance to anyone who can help!
First of all write the method that compares two rows:
private static boolean areIdentical(int[] a1, int[] a2) {
if(a1.length != a2.length) return false;
for(int i = 0; i < a1.length; i++) {
if(a1[i] != a2[i]) return false;
}
return true;
}
Now you can use this method to compare the rows. Just take every row from the array and compare it with every row below. Something like the next:
public static boolean duplicates(int[][] list) {
for (int j = 0; j < list.length; j++) {
if(j == list.length-1) return false; //don't need to compare last row
for (int i = j + 1; i < list.length; i++) {
if(areIdentical(list[j], list[i])) return true;
}
}
return false;
}
You can easily modify this code to count duplicates.

Trouble with randomly generated arrays

So I am working on a assignment that deals with randomly generated arrays. Here is the assignment:
Write the following function that tests whether a two-dimensional list has four consecutive numbers of the same value, either horizontally, vertically, or diagonally. public static boolean isConsecutiveFour(int[][] values) Write a test program that prompts the user to enter the number of rows and columns of a two-dimensional list and then use a random number generator to fill the array and print it out. Display True if the list contains four consecutive numbers with the same value. Otherwise, display False.
I got everything else done, and it seems to work, but I am stuck on the randomly generating the array part. What is supposed to happen is the user is supposed to enter in the amount of rows and columns for an array, then it is generated. Then, the array is tested to find out whether or not four consecutive numbers exist. When I come to test the problem, it does not actually display the numbers. I am at a loss, and really confused ( Can anyone help me or give me a hint? It would be greatly appreciated. Thank You!
import java.util.Random;
import java.util.Scanner;
public class ConsecutiveFour {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Random r = new Random();
System.out.print("Enter number of rows: ");
int rows = input.nextInt();
input.nextLine();
System.out.print("Enter number of columns: ");
int columns = input.nextInt();
input.nextLine();
int[][] matrix = new int[rows][columns];
// generate some random boolean values
boolean[] booleans = new boolean[10];
for (int i = 0; i < booleans.length; i++) {
booleans[i] = r.nextBoolean();
}
for (boolean b : booleans) {
System.out.print(b + ", ");
}
System.out.println("");
}
public static boolean isConsecutiveFour(int[][] values) {
boolean cons = false;
int
//tests horizontally
for (int r=0; r < rows; r++) {
for (int c=0; c < columns - 3; c++){
if (values[c][r] == values[c+1][r] &&
values[c][r] == values[c+2][r] &&
values[c][r] == values[c+3][r]) {
cons = true;
}
}
}
//tests vertically
for (int r=0; r < rows - 3; r++) {
for (int c=0; c < columns; c++){
if (values[c][r] == values[c][r+1] &&
values[c][r] == values[c][r+2] &&
values[c][r] == values[c][r+3]) {
cons = true;
}
}
}
//tests diagonally (going down and to the right)
for (int r=3; r < rows; r++) {
for (int c=0; c < columns - 3; c++) {
if (values[c][r] == values[c+1][r-1] &&
values[c][r] == values[c+2][r-2] &&
values[c][r] == values[c+3][r-3]) {
cons = true;
}
}
}
//tests diagonally (going down and to the left)
for (int r=0; r < rows - 3; r++) {
for (int c=0; c < columns - 3; c++) {
if (values[c][r] == values[c+1][r+1] &&
values[c][r] == values[c+2][r+2] &&
values[c][r] == values[c+3][r+3]) {
cons = true;
}
}
}
return cons;
}
}
To start both of the input.nextLine(); lines are unnecessary. Your input.nextInt(); will be enough to bring in the two values that you need.
It might be easier for you to generate the exact number of random numbers that you need. Seeing how this is an assignment i'll throw you some pseudo code to work through.
for (int i = 0; i < rows; i++) {
for (int k = 0; i < columns; k++) {
int ranNum // Generate random number
// Place random number in matrix[i][k]
}
}
// Send array through checks
Is this the problem you are having or am I misunderstanding your confusion?

how to check if a number I try to add already exist in the column and row?(2d arrays )

int [][]a=new int[9][9] //creates a "square" with 81 0's
How do I go about checking if a input (when filling out the array) already exist in the column or row?
For example, for the row 0, how can I make sure I don't get the number 9 two times (for instance, once on row 0, column 0 and second on row 0 column 1)? I can't seem to figure out how to go about this (all I know is that I'll probably need two for loops? and a if statement. I'm not sure how to go about the if statement tho).
public static void main(String[] args)
{
int[][] a = new int[9][9];
boolean areThereDuplicates;
int input = 9; // or any input of course
int row = 0; // or any row
int column = 0;// or any column
areThereDuplicates = checkDuplicates(input, row, column, a);
if (!areThereDuplicates) // if there are no duplicates, input value
a[row][column] = input;
}
public static boolean checkDuplicates(int numChecked, int row, int column, int[][] arr)
{
// checks row
for (int j = 0; j < arr[row].length; j++)
{
if (arr[row][j] == numChecked)
return true;
}
// checks column
for (int k = 0; k < arr.length; k++)
{
if (arr[k][column] == numChecked)
return true;
}
return false;
}
One important thing I wanted to point out is the for loop that checks the column. arr.length does not return 81; rather it returns 9. arr[row].length also returns how many columns there are in the specified row.
Quick draft, not tested but should work:
a[x][y] = newValue; // e.g. 9
return checkDuplicates(x, y, newValue); // returns true if a duplicate is found
public boolean checkDuplicates(int x, int y, int newValue) {
for (int i=0; i<9; i++) {
if (i!=x && a[i][y]==newValue)
return true;
}
for (int i=0; i<9; i++) {
if (i!=y && a[x][i]==newValue)
return true;
}
return false;
}

Sudoku Checker 2d array Java

So im having a bit of problem with my code.. It's suppose to cross check rows and columns for same integers.
this is what i have so far.. but when i run it, it only seems to check the first integer only. (for example the first line of the sudoku board reads. 1 2 2 2 2 2 2 2 2 2) it wont detect the obvious multiple 2's but if i change the input to 1 1 2 2 2 2 2 2 2 the error will come up of multiple 1's in this case. the multiple any suggestions to tweak my loops to make it go through the columns?
public static void validate(final int[][] sudokuBoard) {
int width = sudokuBoard[0].length;
int depth = sudokuBoard.length;
for (int i = 0; i < width; i++) {
int j = i;
int reference = sudokuBoard[i][j];
while (true) {
if ((j >= width) || (j >= depth)) {
break;
}
else if (i == j){
// do nothing
}
else if (j < width) {
int current = sudokuBoard[i][j];
if (current == reference) {
System.out.print("Invalid entry found (width)" + "\n");
System.out.print(current + "\n");
// invalid entry found do something
}
} else if (j < depth) {
// note reversed indexes
int current = sudokuBoard[j][i];
if (current == reference) {
System.out.print("Invalid entry found (depth)" + "\n");
System.out.print(current + "\n");
// invalid entry found do something
}
}
j++;
}
Your code is more complex than it should be. Why put everything in one single function when you could split in several different functions?
public static void Validate(final int[][] sudokuBoard)
{
int width = sudokuBoard[0].length;
int depth = sudokuBoard.length;
for(int i = 0; i < width; i++)
if(!IsValidRow(sudokuBoard, i, width))
{
//Do something - The row has repetitions
}
for(int j = 0; j < height; j++)
if(!IsValidColumn(sudokuBoard, j, width))
{
//Do something - The columns has repetitions
}
}
static bool IsValidRow(int[][] sudokuBoard, int referenceRow, int width)
{
//Compare each value in the row to each other
for(int i = 0; i < width; i++)
{
for(int j = i + 1; j < width; j++)
{
if(sudokuBoard[referenceRow][i] == sudokuBoard[referenceRow][j])
return false
}
}
return true;
}
static bool IsValidColumn(int[][] sudokuBoard, int referenceColumn, int height)
{
//Compare each value in the column to each other
for(int i = 0; i < height; i++)
{
for(int j = i + 1; j < height; j++)
{
if(sudokuBoard[i][referenceColumn] == sudokuBoard[j][referenceColumn])
return false
}
}
return true;
}
That way, your code is much more easily maintainable/readable. This code above hasn't been tested, but it should be about right.
I suggest debugging this code step by step to really understand what's going on, if that's not clear for you.
Given the constraints of sudoku (a row of n cells must contain the numbers 1-n only) you don't need an order n^2 search (per row or column), you can do it order n by keeping a bit array indicating which numbers you've seen. Here's the pseudo-code for checking rows, do the same for columns:
for i in 0 to depth-1 // rows
boolean seen[] = new seen[width];
for j in 0 to width-1 // columns
if seen[board[i][j]-1] == true
duplicate number
else
seen[board[i][j]-1] = true
I would break the functionality into smaller boolean checks. This way, you can validate row by row, column by column, and square by square. For instance
private boolean isValidRow(int[] row) {
// Code here to check for valid row (ie, check for duplicate numbers)
}
private boolean isValidColumn(int[] column) {
// Code here to check for valid column
}
private boolean isValidSquare(int[][] square) {
// Code here to check for valid square
}
Note that rows and columns only need to be passed a 1 dimensional array. Squares are a 2 dimensional array as you need to check a 3x3 area. You can also treat these methods as static as their functionality is independent of the Sudoku board instance.
Edit: A suggestion on row/column/square validation is to use a HashSet. Sets can only have 1 element of a certain value, so you can add elements and look for a failure. For example:
HashSet<Integer> hs = new HashSet<Integer>();
for(int i = 0; i < 9; i++) {
if(!hs.add(integerArray[i])) // HashSet.add returns 'false' if the add fails
// (ie, if the element exists)
return false;
}
return true;

Categories