Using Integer[] vs. int[] - java

I am trying to solve the following problem: "Write an algorithm to print all the ways of arranging eight queens on an 8x8 chess board so that none of them share the same row, column or diagonal (i.e. no two queens attack each other.)"
I am having trouble understanding why the author used Integer[] instead of the more common int[], for example in "Integer[] columns" and "ArrayList results" which are parameters to placeQueens. My hypothesis is that this is due to generics in Java, but I'm not entirely sure.
Code snippet below. Link to complete code at bottom of page.
public static int GRID_SIZE = 8;
/* Check if (row1, column1) is a valid spot for a queen by checking if there
* is a queen in the same column or diagonal. We don't need to check it for queens
* in the same row because the calling placeQueen only attempts to place one queen at
* a time. We know this row is empty.
*/
public static boolean checkValid(Integer[] columns, int row1, int column1) {
for (int row2 = 0; row2 < row1; row2++) {
int column2 = columns[row2];
/* Check if (row2, column2) invalidates (row1, column1) as a queen spot. */
/* Check if rows have a queen in the same column */
if (column1 == column2) {
return false;
}
/* Check diagonals: if the distance between the columns equals the distance
* between the rows, then they're in the same diagonal.
*/
int columnDistance = Math.abs(column2 - column1);
int rowDistance = row1 - row2; // row1 > row2, so no need to use absolute value
if (columnDistance == rowDistance) {
return false;
}
}
return true;
}
public static void placeQueens(int row, Integer[] columns, ArrayList<Integer[]> results) {
if (row == GRID_SIZE) { // Found valid placement
results.add(columns.clone());
} else {
for (int col = 0; col < GRID_SIZE; col++) {
if (checkValid(columns, row, col)) {
columns[row] = col; // Place queen
placeQueens(row + 1, columns, results);
}
}
}
}
Source for question/code: Cracking the Coding Interview. Link to complete code: https://github.com/gaylemcd/ctci/blob/master/java/Chapter%209/Question9_9/Question.java

In Java, Integer represents an object, while int is a primitive type. The Integer class supports more functions and can hold null values. In addition, ArrayList can only contain objects such as Integer.
ArrayList<int[]> results = new ArrayList<int[]>();
In the revised code above, int[] would still work because it is considered an object. However, the author may be seeking consistency or would need the extra functionality of the Integer object. It is a matter of the author's preference or ignorance.

You may think that the first line of the main (from the link you've provided):
ArrayList<Integer[]> results = new ArrayList<Integer[]>();
Must use Integer, but as comments suggest, it's not the case.
ArrayList<int[]> results = new ArrayList<int[]>();
Would also worked. So it's just the author's preference in that case.

Related

How to find most profitable Path in 2-Dimensional Array

I'm trying to implement a game where the viable moves are down-left and down-right.
The parameter for the function is for the size of the array, so if you pass 4 it will be a 4 by 4 array.
The starting position is the top row from any column. Every element in the array is a number in the range 1-100, taken from a file. I need to find the resulting value for the most profitable route from any starting column.
My current implementation will compare the right position and left position and move to whichever is higher. The problem is, for example, if the left position is lower in value than the right, but the left position will provide more profit in the long run since it can access higher value elements, my algorithm fails.
Here is a demo:
84 (53) 40 62
*42* 14 [41] 57
76 *47* 80 [95]
If we start at number 53. The numbers enclosed in * are the moves that my algorithm will take, but the numbers enclosed in [] are the moves my algorithm should take.
This is my code:
import java.util.ArrayList;
import java.util.Scanner;
public class bestPathGame{
private int[][] grid;
private int n;
public bestPathGame(int num){
Scanner input = new Scanner(System.in);
n = num;
grid = new int[n][n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
grid[i][j] = input.nextInt();
}
}
}
public static void main(String[] args){
bestPathGame obj = new bestPathGame(Integer.parseInt(args[0]));
obj.bestPath();
}
private boolean moveLeftBetter(int r,int c){
if(c <= 0){
return false;
} else if (c >= n -1 ){
return true;
}
return grid[r][c-1] > grid[r][c+1];
}
public void bestPath(){
ArrayList<Integer> allOptions = new ArrayList<>();
for(int k = 0; k < n; k++){
int row = 0;
int col = k;
int collection = grid[row][col];
while(row < n - 1){
row += 1;
if(moveLeftBetter(row,col)){
col-=1;
} else{
col+=1;
}
collection += grid[row][col];
}
allOptions.add(collection);
}
System.out.println(allOptions.stream().reduce((a,b)->Integer.max(a,b)).get());
}
}
Greedy algorithm vs Dynamic programming
There's an issue with the logic of your solution.
Basically, what you are implemented is a called a greedy algorithm. At each step of iteration, you are picking a result that optimal locally, assuming that this choice will lead to the optimal global result. I.e. your code is based on the assumption that by choosing a local maximum between the two columns, you will get the correct global maximum.
As a consequence, your code in the bestPath() method almost at each iteration will discard a branch of paths based on only one next value. This approach might lead to incorrect results, especially with large matrixes.
Greedy algorithms are rarely able to give an accurate output, usually their result is somewhat close but not precise. As an upper-hand, they run fast, typically in O(n) time.
For this problem, you need to use a dynamic programming (DP).
In short, DP is an enhanced brute-force approach which cashes the results and reuses them instead of recalculating the same values multiple times. And as well, as a regular brute-force DP algorithms are always checking all possible combinations.
There are two major approaches in dynamic programming: tabulation and memoization (take a look at this post for more information).
Tabulation
While implementing a tabulation first you need to create an array which then need to be prepopulated (completely or partially). Tabulation is also called the bottom-up approach because calculation start from the elementary edge cases. Every possible outcome is being computed based on the previously obtained values while iterating over this array. The final result will usually be stored in the last cell (in this case in the last row).
To implement the tabulation, we need to create the matrix of the same size, and copy all the values from the given matrix into it. Then row by row every cell will be populated with the maximum possible profit that could be obtained by reaching this cell from the first row.
I.e. every iteration will produce a solution for a 2D-array, that continuously increases by one row at each step. It'll start from the array that consists of only one first row (no changes are needed), then to get the profit for every cell in the second row it's values has to be combined with the best values from the first row (that will be a valid solution for 2D-array of size 2 * n), and so on. That way, solution gradually develops, and the last row will contain the maximum results for every cell.
That how the code will look like:
public static int getMaxProfitTabulation(int[][] matrix) {
int[][] tab = new int[matrix.length][matrix.length];
for (int row = 0; row < tab.length; row++) { // populating the tab to preserve the matrix intact
tab[row] = Arrays.copyOf(matrix[row], matrix[row].length);
}
for (int row = 1; row < tab.length; row++) {
for (int col = 0; col < tab[row].length; col++) {
if (col == 0) { // index on the left is invalid
tab[row][col] += tab[row - 1][col + 1];
} else if (col == matrix[row].length - 1) { // index on the right is invalid
tab[row][col] += tab[row - 1][col - 1];
} else {
tab[row][col] += Math.max(tab[row - 1][col - 1], tab[row - 1][col + 1]); // max between left and right
}
}
}
return getMax(tab);
}
Helper method responsible for extracting the maximum value from the last row (if you want to utilize streams for that, use IntStream.of(tab[tab.length - 1]).max().orElse(-1);).
public static int getMax(int[][] tab) {
int result = -1;
for (int col = 0; col < tab[tab.length - 1].length; col++) {
result = Math.max(tab[tab.length - 1][col], result);
}
return result;
}
Memoization
The second option is to use Memoization, also called the top-down approach.
As I said, DP is an improved brute-force algorithm and memoization is based on the recursive solution that generates all possible outcomes, that is enhanced by adding a HashMap that stores all previously calculated results for every cell (i.e. previously encountered unique combination of row and column).
Recursion starts with the first row and the base-case of recursion (condition that terminates the recursion and is represented by a simple edge-case for which output is known in advance) for this task is when the recursive call hits the last row row == matrix.length - 1.
Otherwise, HashMap will be checked whether it already contains a result. And if it not the case all possible combination will be evaluated and the best result will be placed into the HashMap in order to be reused, and only the then the method returns.
Note that tabulation is usually preferred over memoization, because recursion has significant limitations, especially in Java. But recursive solutions are sometimes easier to came up with, so it's completely OK to use it when you need to test the idea or to prove that an iterative solution is working correctly.
The implementation will look like that.
public static int getMaxProfitMemoization(int[][] matrix) {
int result = 0;
for (int i = 0; i < matrix[0].length; i++) {
result = Math.max(result, maxProfitHelper(matrix, 0, i, new HashMap<>()));
}
return result;
}
public static int maxProfitHelper(int[][] matrix, int row, int col,
Map<String, Integer> memo) {
if (row == matrix.length - 1) { // base case
return matrix[row][col];
}
String key = getKey(row, col);
if (memo.containsKey(key)) { // if cell was already encountered result will be reused
return memo.get(key);
}
int result = matrix[row][col]; // otherwise result needs to be calculated
if (col == matrix[row].length - 1) { // index on the right is invalid
result += maxProfitHelper(matrix, row + 1, col - 1, memo);
} else if (col == 0) { // index on the left is invalid
result += maxProfitHelper(matrix, row + 1, col + 1, memo);
} else {
result += Math.max(maxProfitHelper(matrix, row + 1, col - 1, memo),
maxProfitHelper(matrix, row + 1, col + 1, memo));
}
memo.put(key, result); // placing result in the map
return memo.get(key);
}
public static String getKey(int row, int col) {
return row + " " + col;
}
Method main() and a matrix-generator used for testing purposes.
public static void main(String[] args) {
int[][] matrix = generateMatrix(100, new Random());
System.out.println("Tabulation: " + getMaxProfitTabulation(matrix));
System.out.println("Memoization: " + getMaxProfitMemoization(matrix));
}
public static int[][] generateMatrix(int size, Random random) {
int[][] result = new int[size][size];
for (int row = 0; row < result.length; row++) {
for (int col = 0; col < result[row].length; col++) {
result[row][col] = random.nextInt(1, 101);
}
}
return result;
}

Store 2d array positions in ArrayList

I want to store several 2d array positions in an ArrayList and I've set it up like so:
ArrayList<Integer> playedValues = new ArrayList<Integer>();
playedValues.add(dataArray[0][1]);
playedValues.add(dataArray[0][2]); //example of adding 2d array positions
int size = playedValues.size(); //get size of ArrayList
int gridIndex = playedValues.get(size - 1); //trying to set gridIndex to dataArray[0][2]
cell.setCell(0, gridIndex); //this is where the error occurs
//trying to pass gridIndex to here
public void setCell(int value, int gridIndex) {
gridIndex = value;
}
My issue is when I try and pass gridIndex as a parameter to setCell, I get a NullPointerException.
The method I'm passing it to seems to work fine in my tests, so I assume gridIndex is not being set properly. How do I make playedValues store dataArray[][] itself instead of the information dataArray[][] holds?
The solution you were looking for
After talking with you in chat, we determined that you were making a Sudoku game, and you wanted to store moves, and be able to undo those moves.
You have the board stored as sudokuGrid which is a 2d int array. You need to be able to make changes to certain cells (row, column). You also need to be able to store moves, (row, column), and in order. Then you can use both of these features together, and allow your users to undo their moves.
Let's focus on making changes to a cell first.
Undo'ing a move
We can write a method that takes in a row and a column, and changes the value of the cell at (row, column) back to 0. (Undo-ing a move).
We should be able to call this method like so:
int testRow = 4, testColumn = 1;
undoMove(testRow, testColumn, sudokuGrid);
Of course, later we'll use row's and column's from previous moves, but we need to be able to test right now. The undoMove method will be written like so:
public void undoMove(int row, int column, int[][] board) {
board[row][column] = 0;
}
It's very important that we pass in sudokuGrid to undoMove. Otherwise, undoMove wouldn't be able to make permanent changes to the game board. You can read the link I gave farther below for more information on why you are able to make changes to sudokuGrid.
Now, we need to focus on how we can store moves.
Storing moves
We have a few options available, but the easiest in my opinion, would be to make an ArrayList and store Move's in it. Of course, Java hasn't defined Move's for us. We will have to make our own class to define a Move.
If you're unfamiliar with making classes, you can learn the basics here, and here.
Here's what our Move class might look like:
class Move {
int row, column;
public Move(int row, int column) {
this.row = row;
this.column = column;
}
}
public void undoMove(int row, int column, int[][] board) {
board[row][column] = 0;
}
This simply says that each Move will have a row, a column.
We can now store the row and column of the cell where each move was played.
Now we can make an ArrayList to hold our Move's:
ArrayList<Move> moves = new ArrayList<Move>();
We can make a Move object each time that a user makes a move like so:
// You'll need to get the row and column
// before you make the Move object
Move currentMove = new Move(row, column);
Now anytime we want to undo a move, we can simply do this:
Move moveToUndo = moves.get( moves.size() - 1 );
undoMove(moveToUndo.row, moveToUndo.column, sudokuGrid);
moves.remove( moves.size() - 1 );
Now all together!
class Move {
int row, column;
public Move(int row, int column) {
this.row = row;
this.column = column;
}
}
public void undoMove(int row, int column, int[][] board) {
board[row][column] = 0;
}
// Later on, in your game loop method
ArrayList<Move> moves = new ArrayList<Move>();
// Adding moves
// In your program, you'll get the row and column from what
// the user types in or clicks on.
int row = 1, column = 7;
moves.add( new Move(row, column) );
row = 6, column = 8;
moves.add( new Move(row, column) );
// Undo'ing moves
Move moveToUndo = moves.get( moves.size() - 1 );
undoMove(moveToUndo.row, moveToUndo.column, sudokuGrid);
moves.remove( moves.size() - 1 );
You could even re-write the undoMove method to take in a Move, rather than a row and a column, and that would look very clean. You could also write a method undoLastMove that would automate some of this process.
Fixing your ArrayList problem
I'm not quite sure what you intend to use the ArrayList playedValues for, so I have to make a somewhat educated guess that you want to have an ArrayList hold arrays, not single values.
That is very simple to do!
Your current declaration:
ArrayList<Integer> playedValues = ArrayList<Integer>();
Sets up playedValues to hold Integer or int values. To instead set up playedValues to hold arrays of int's, do this:
ArrayList<Integer[]> playedValues = ArrayList<Integer[]>();
Then playedValues will store arrays of Integer's or int's.
You can use the ArrayList like so:
ArrayList<Integer[]> playedValues = ArrayList<Integer[]>();
int[] arrayOne = {1, 2, 3, 4, 5};
// Adding arrays to the list
playedValues.add(arrayOne);
// Iterating through all arrays in playedValues
for(int i = 0; i < playedValues.size(); i++) {
int[] currentArray = playedValues.get(i);
// Then, of course, you can loop over each array like normal:
for(int j = 0; j < currentArray.length; j++) {
System.out.println(
"Array #" + i + " - Element #" + j + " = " + currentArray[i][j]
);
}
}
There's an even better way!
If you're using an ArrayList the same way as you would a 2d array, but you still want all of the flexibility and features of an ArrayList, then do this:
ArrayList<ArrayList<Integer>> playedValues = ArrayList<ArrayList<Integer>>();
That sets up playedValues to be an ArrayList which holds ArrayLists which hold int's. Very similar to using int[][] which uses an array that holds arrays that hold ints'.
The above code can be implemented with this new ArrayList of ArrayLists, like so:
ArrayList<ArrayList<Integer>> playedValues = ArrayList<ArrayList<Integer>>();
int[] arrayOne = {1, 2, 3, 4, 5};
// Adding values to the playedValues
playedValues.add( Arrays.asList(arrayOne) );
// Iterating through all values in playedValues
for(int i = 0; i < playedValues.size(); i++) {
for(int j = 0; j < playedValues.get(i).size(); j++) {
System.out.println(
"Row #" + i + " - Column #" + j + " = " + playedValues.get(i).get(j)
);
}
}
If you wanted to store, maybe a 9x9 grid, you could easily do that like this:
ArrayList<ArrayList<Integer>> playedValues = ArrayList<ArrayList<Integer>>();
int[] sampleRow = {0, 0, 0, 0, 0, 0, 0, 0, 0};
for(int i = 0; i < 9; i++) {
playedValues.add( Arrays.asList(sampleRow) );
}
But, should you use ArrayList?
I don't see a huge need for using an ArrayList here. When I see the code you have and read what you are trying to do, I immediately think 2d array.
There isn't anything in your code, or my answer, that can't be done with a 2d array. It may make things simpler too. The only issue, is if you need to dynamically add arrays. A 2d array can't do that.
Here is the same implementation as above, with a 2d array:
// 100 for rows and columns was chosen arbitrarily.
int[][] playedValues = new int[100][100];
int[] arrayOne = {1, 2, 3, 4, 5};
int[] arrayTwo = {1337, 9001, 1111111, 22222, 33333, 444, -1, -123, 246};
// Adding arrays to the list
playedValues[0] = arrayOne;
playedValues[1] = arrayTwo;
// Iterating through all arrays in playedValues
for(int i = 0; i < playedValues.length; i++) {
for(int j = 0; j < playedValues[i].length; j++) {
System.out.println(
"Array #" + i + " - Element #" + j + " = " + currentArray[i][j]
);
}
}
And the setCell method:
public void setCell(int value, int row, int column, int[][] grid) {
grid[row][column] = value;
}
Fixing the setCell method
If we have an ArrayList which stores arrays of int's, we can change a certain cell with this implementation:
// Making a call to set the cell in the 1st row at the 4th column, to 0
setCell(0, 1, 4, playedValues);
public void setCell(int value, int row, int column, ArrayList<Integer[]> grid) {
int[] rowArray = grid.get(row);
rowArray[column] = value;
}
Original Error
The problem isn't with gridIndex, it's with cell.
You can get a NullPointerException from an int, since all int's have default/null values of 0 in Java. See the documentation here, here, here, and this post's answers, for proof of this.
So the problem isn't with the setCell method, it's with your cell variable. The NullPointerException is being thrown because cell is null, not anything you pass to setCell.
Why setCell didn't originally work
It is true, as pointed out by other answers, that the method setCell won't actually do anything noticeable. This is because Java is pass by value, not pass by reference. You can read this post for a detailed explanation.
What this means behind the scenes, is that whatever actual number values you pass to setCell as value and gridIndex, setCell will have the values of, but not the references.
This code:
int gridIndex = 10, myValue = 2;
setCell(myValue, gridIndex);
will call setCell and pass the values of gridIndex and myValue, which are 10 and 2. The setCell method never sees the actual variables gridIndex and myValue, setCell has no reference to those variables, it only ever sees the values 10 and 2.
This can be confusing because the values are stored in variables within setCell, the variables you specify to be the parameter names (int value, int gridIndex), but these variables, are not the variables you passed to setCell. See this code:
public static void main(String[] args) {
int gridIndex = 10, myValue = 9999;
setCell(myValue, gridIndex);
System.out.println(gridIndex);
}
public static void setCell(int value, int gridIndex) {
// In here, value is NOT the same variable, myValue, that
// we passed in. Just the same, gridIndex, is not the same
// variable that we passed in from main.
// In here, value and gridIndex have the SAME VALUES
// as the variables we pass in, but they are not the same
// variables. They are newly made variables, with the same values.
}
Also look at this code:
public static void main(String[] args) {
setCell(10, 9999);
System.out.println(gridIndex);
}
public static void setCell(int value, int gridIndex) {
gridIndex = value;
}
We didn't pass a variable to setCell, but inside setCell we changed the variable gridIndex to be equal to value. Will this tell Java that the new value of the number 9999 should really be 10? Of course not. We aren't changing what was passed in, we are changing variables that hold the values that were passed in.
An easy way to think about what is happening, is to remember that whenever you use an int variable in Java, you could replace the variable name with the value it holds, and the code would remain exactly the same.
Take this code for example:
int gridIndex = 10, myValue = 9999;
setCell(myValue, gridIndex);
an equilivant code is:
setCell(10, 9999);
And as we just saw above, of course we can't change the value of 10 or 9999. We can't just decide that numbers are equal other numbers. Of course we can change the numbers that are held in int's, but there aren't any int variables being delivered to setCell, only number values like 10 or 9999.
public void setCell(int value, int gridIndex) {
gridIndex = value;
}
The above code does nothing. It takes two arguments, and locally sets one of the arguments to the other. Then since both of the variables were declared within the function, they are both gone when it exits.
Since this method just sets gridIndex, why not just set it directly?
gridIndex = 0;
EDIT: example of why this doesn't work.
I tried this in my IDE - it is exactly the same setCell method you have.
public static void main(String[] args) {
int gridIndex = 10;
setCell(0, gridIndex);
System.out.println(gridIndex);
}
public static void setCell(int value, int gridIndex) {
gridIndex = value;
}
The console prints 10, because setCell does nothing. It doesn't set the value of gridIndex, it doesn't edit any variables. It does nothing, because the only values it changes are values which are declared in its signature, and which are lost when the method exits as a result.

Preventing crashes if adding an item to a location that doesn't exists in a 2D array

My code:
public class MultiArr {
private int row;
private int col;
private int MultiA[][];
public MultiArr(int row, int col) {
this.row = row;
this.col = col;
MultiA = new int[row][col];
}
public void setItem(int row, int col, int item) {
if (row > MultiA.length || col > MultiA.length) {
System.out.println("out of bound");
} else {
MultiA[row][col] = item;
}
}
public int getItem(int row, int col) {
return MultiA[row][col];
}
public int getLength() {
return MultiA.length;
}
public static void main(String[] args) {
MultiArr test = new MultiArr(1,2);
test.setItem(1,0,1);
//System.out.println(test.getItem(0,0));
//System.out.println(test.getLength());
}
}
So I create this class to create a 2d array of ints (for testing purposes) and it works for the most part
but the problem I'm facing is when you try to add an item to a location which doesnt
exists, for examples:
Suppose you say:
MultiArr test = new MultiArr(2,2);
This creates:
_01_
0 |XX
1 |XX
And now suppose you want to set the value 1 at postion (0, 1):
test.setItem(0,1,1);
This works, but however when you try to put in a position that doesnt exist
it will crash, for example:
test.setItem(3,2,1);
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at mazegame.MultiArr.setItem(MultiArr.java:19)
at mazegame.MultiArr.main(MultiArr.java:33)
To solve this what I did was well if you put in a number for row and its higher then the
number of row you created or if you put in a number for column and its higher than
the number you put when you created the array than it should crash, so for this I put and
if-else to take care of that situation.
But then theres a another problem and thats if you end up with like multiple rows and 1 column
Example:
MultiArr test = new MultiArr(1,2);
_0 1
0 |X X
test.setItem(1,0,1);
This now crashed because that location doesnt exists and so it skips the if-else that I put to try to prevent the previous error.
I have been stuck of this for a while now and I was wondering if anyone knows a better and easier way to prevent it from crashing if the location doesn't exist, thanks for anyone that helps :)
It is not a good idea to handle this by printing a message. Trying to set a value to an element of an array that doesn't exist is an error of programming and the program should not be able to continue its execution after this. However, if you really want to do it, you must change
if (row > MultiA.length || col > MultiA.length)
with
if (row >= MultiA.length || col >= MultiA[row].length)
Indeed, don't forget that an array arr is indexed from 0 to arr.length - 1, so arr.length is also an invalid index (that's why so need a >= rather than a >. Finally, the other thing you had wrong was that you didn't take in account the number of columns but the number of rows (MultiA.length) in both parts of the test.
Replace
if (row > MultiA.length || col > MultiA.length) {
With
if (row > MultiA.length || col > MultiA[row].length) {
MultiA.length only gets the length of the array. MultiA is an array of arrays though. You want to get the length of the array inside.
Also, as Alexander Zhak said, the > should be a >=, because arrays in Java start at index 0 and go to length-1.
Java arrays start counting at 0, so an array new int[1][2]; has the valid locations {0, 0} and {0, 1}, so you should adjust your code to
if (row >= MultiA.length || col >= MultiA[row].length) {

analyzing a 2D array by columns

I have the following 2D array and I want to compare all the columns with each other.
int [][] myarray={{1,2,3},{1,2,3},{1,2,3}};
So what I want to see is if column 1 (all 1's) is equal to the values in column 2 (all 2's).
Ps. the array size is not just limited to this.
It's not quite clear from your question whether you want to compare all columns to each other, or just a single column to another single column (for example column 1 to column 2). Assuming you meant the latter, you could do this.
public boolean columnsIdentical(int[][] array, int colIndex1, int colIndex2) {
for (int row = 0; row < array.length; row++ ) {
if (array[row][colIndex1] != array[row][colIndex2]) {
return false;
}
}
return true;
}
for (int i=0;i<myarray[0].length;i++) {
int comp=myarray[0][i];
for (int j=1;j<myarray.length;j++) {
if (myarray[j][i] != comp) {
// no match
} else {
// match
}
}
}
To test all pairs of columns you need 3 loops
Innermost compares elements of columns A and B
Middle loops through B, skipping columns already checked
Outermost loops through A for all columns

Comparing integers of rows and columns of a 2d array. Sudoku

Hey I'm having trouble getting my code to compare the integers of a given row or column and block to make sure there are no duplicates within those parameters. I don't know if it would be a good idea separating the three contraints in 3 different methods or just trying to attempt to do all at once.
public static rowCheck(int[][] nsudokuBoard) {
for (int i =0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
// (nsudokuBoard)
}
}
}
this is my code im starting. before you guys bash on me for not even being able to compile this im stuck on how to compare all the values of a row of the 2d array.
You can compare all the values of the 2d array as shown in the code below:
void validate(final int[][] nsudokuBoard) {
final int width = nsudokuBoard[0].length;
final int depth = nsudokuBoard.length;
for (int i = 0; i < width; i++) {
int j = i;
int reference = nsudokuBoard[i][j];
do {
if (j < width) {
int current = nsudokuBoard[i][j];
if (current == reference) {
// invalid entry found do something
}
}
if (j < depth) {
// note reversed indexes
int current = nsudokuBoard[j][i];
if (current == reference) {
// invalid entry found do something
}
}
++j;
} while ((j >= width) || (j >= depth));
}
}
I haven't tried to compile this code, but it should give you an idea of how to accomplish your task. I would suggest that rather than passing in int[][] sudokuBoard that you should define a class which encapsulates the concept of a SudokuSquare and pass in SudokuSquare[][] , that way your validate method can return a List<SudokuSquare> containing all the offending entries.
I'll show how you might do it for one row, and then you can figure out the rest. I'm assuming your values are 1 through 9 inclusive, and that you don't have any zeroes or any "unfilled entries."
boolean isRowValid(int[][] grid, int row) {
boolean[] seen = new boolean[9];
int row; // chosen somewhere else
for (int col = 0; col < 9; col++) {
if (seen[grid[row][col] - 1]) { // if we've seen this value before in this row
return false; // there is a duplicate, and this is a bad sudoku
}
seen[grid[row][col] - 1] = true; // mark us as having seen this element
}
return true; // we're all good
}
return true; // this row is fine
make a class Cell with fields row,col,block,value; then make a class Matrix with field cells = cell[], fill matrix.
make a class checker with main method Matrix matrix = init(int[][]) and check(matrix), where init(ยท) fills the matrix.
boolean ok = check(matrix) where check(Matrix) does if(!rowcheck())return false; if(!colcheck()) return false etc;
create some methods like getrows(), getrow(r) and for(Cell cell: matrix.values()) to filter out the ones you want.
a bit tedious but i have done it and it is solid as rock.
As a note, filtering over matrix may seem stupid but computers are fast and the problem is O(1) since it is 9x9.

Categories

Resources