Java array out of bounds - sudoku - java

My code for filling sudoku board looks like this:
public class SudokuBoard {
static int N = 9;
static int[][] grid = new int[N][N];
static void printGrid()
{
for (int row = 0; row < N; row++)
{
for (int col = 0; col < N; col++) {
System.out.printf("%5d", grid[row][col]);
}
System.out.println("\n");
}
}
private static boolean checkRow(int row, int num)
{
for( int col = 0; col < 9; col++ )
if(grid[row][col] == num)
return false;
return true;
}
private static boolean checkCol(int col, int num)
{
for( int row = 0; row < 9; row++ )
if(grid[row][col] == num)
return false;
return true;
}
private static boolean checkBox(int row, int col, int num)
{
row = (row / 3) * 3;
col = (col / 3) * 3;
for(int r = 0; r < 3; r++)
for(int c = 0; c < 3; c++)
if(grid[row+r][col+c] == num)
return false;
return true;
}
public static boolean fillBoard(int row, int col, int[][] grid)
{
if(row==9)
{
col = 0;
if(col++ == 9)
return true;
}
if(grid[row][col] != 0)
return fillBoard(row+1, col, grid);
for(int num = 1; num <=9; num++)
{
if(checkRow(row,num) && checkCol(col,num) && checkBox(row,col,num)){
grid[row][col] = num;
if(fillBoard(row+1, col, grid))
return true;
}
}
grid[row][col] = 0;
return false;
}
static public void main(String[] args){
fillBoard(0, 0, grid);
printGrid();
}
}
It uses backtrack algorithm to check if placement of numbers are good according to sudoku game puzzle rules.
It throws errors:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9
at SudokuBoard.fillBoard(SudokuBoard.java:68)
at SudokuBoard.fillBoard(SudokuBoard.java:74) x9
at SudokuBoard.main(SudokuBoard.java:84)
Where is it out of bounds? I cannot see that...

This block looks wrong:
if(row==9)
{
col = 0;
if(col++ == 9)
return true;
}
I suspect you want this:
if(row==9) {
row = 0;
if(++col == 9)
return true;
}

col++ increments col, but returns the old value. You probably meant to use ++col, which returns the new value. (see Java: Prefix/postfix of increment/decrement operators?)
In your code, when fillBoard(8, 8, grid) is called, col is increased to 9, but (col++ == 9) gets evaluated to false, because col++ returns 8. So you then try to access grid[8][9], which is when the exception is thrown.

Related

Solve Sudoko in Java

I've written the code as per the logic, but my Eclipse console is empty when I click 'Run'.
This is my code:
public class test {
public static void main(String[] args) {
int[][] board = new int[9][9];
helper(board, 0, 0);
}
public static void saveBoard(int[][] board) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
System.out.print(board[i][j]);
}
System.out.println();
}
}
public static void helper(int[][] board, int row, int col) {
if (row == board.length - 1) {
saveBoard(board);
return;
}
if (col == board.length - 1) {
col = 0;
row += 1;
}
for (int i = 1; i <= 9; i++) {
if (isSafe(board, row, col, i)) {
board[row][col] = i;
helper(board, row, col + 1);
}
}
}
public static boolean isSafe(int[][] board, int row, int col, int number) {
// row & column
for (int i = 0; i < board.length; i++) {
if (board[row][i] == number) return false;
if (board[i][col] == number) return false;
}
// grid
int sc = (col / 3) * 3;
int sr = (row / 3) * 3;
for (int i = 0; i < sr + 3; i++) {
for (int j = 0; j < sc + 3; j++) {
if (board[i][j] == number) return false;
}
}
return true;
}
}
or here's a screenshot

Given a matrix find all adjacent same elements

I have a 2D matrix, now I want to pick an element e and see all adjacent elements (i+1,j), (i-1,j) , (i,j+1), (i,j-1) and navigate if they are same as e and count how many are matching like that. Now find the maximum count that is possible.
example:
1 2 3 4
1 2 4 4
4 2 4 5
6 9 4 7
Output: 5.
as 4 is the element that repeats 5 times and all are adjacents, whereas 1 appears only 2 times and 2 appears only 3 times.
How to solve this program? I tried with BFS but got stuck on how to maintain the count here?
static class pair {
int first, second;
public pair(int first, int second) {
this.first = first;
this.second = second;
}
}
static int ROW = 4;
static int COL = 4;
// Direction vectors
static int dRow[] = { -1, 0, 1, 0 };
static int dCol[] = { 0, 1, 0, -1 };
// Function to check if a cell
// is be visited or not
static boolean isValid(boolean vis[][], int row, int col) {
// If cell lies out of bounds
if (row < 0 || col < 0 || row >= ROW || col >= COL)
return false;
// If cell is already visited
if (vis[row][col])
return false;
// Otherwise
return true;
}
static void BFS(int grid[][], boolean vis[][], int row, int col) {
// Stores indices of the matrix cells
Queue<pair> q = new LinkedList<>();
// Mark the starting cell as visited
// and push it into the queue
q.add(new pair(row, col));
vis[row][col] = true;
// Iterate while the queue
// is not empty
int max = 0;
while (!q.isEmpty()) {
pair cell = q.peek();
int x = cell.first;
int y = cell.second;
int v = grid[x][y];
System.out.print(grid[x][y] + " ");
// Go to the adjacent cells
for (int i = 0; i < 4; i++) {
int adjx = x + dRow[i];
int adjy = y + dCol[i];
if (isValid(vis, adjx, adjy)) {
if (grid[adjx][adjx] == v) {
q.add(new pair(adjx, adjy));
vis[adjx][adjy] = true;
}
}
}
}
public static void main(String[] args) {
// Given input matrix
int grid[][] = { .... };
ROW = grid.length;
COL = grid[0].length;
// Declare the visited array
boolean[][] vis = new boolean[ROW][COL];
BFS(grid, vis, 0, 0);
}
You need to iterate over the grid to identify the starting point of each BFS. Also, you need to initialize a new count at the start of each BFS and increment it each time you visit a neighboring cell. Then take the max of each such count.
static int max(int[][] grid)
{
int rows = grid.length;
int cols = grid[0].length;
Queue<Pos> q = new LinkedList<>();
boolean[][] visited = new boolean[rows][cols];
int max = 0;
for(int r=0; r<rows; r++)
{
for(int c=0; c<cols; c++)
{
if(!visited[r][c])
{
q.add(new Pos(r, c));
visited[r][c] = true;
int count = 0;
while(!q.isEmpty())
{
Pos p = q.poll();
count += 1;
for(int d=0; d<4; d++)
{
int i = p.r + dRow[d];
int j = p.c + dCol[d];
if(i >= 0 && i < rows && j >= 0 && j < cols && !visited[i][j] && grid[i][j] == grid[r][c])
{
q.add(new Pos(i, j));
visited[i][j] = true;
}
}
}
max = Math.max(max, count);
}
}
}
return max;
}
Test:
int[][] grid = {{1,2,3,4},
{1,2,4,4},
{4,2,4,5},
{6,9,4,7}};
System.out.printf("Max = %d%n", max(grid));
Output:
Max = 5
Bi Simple!
public static int findMaxAdjacentCount(int[][] grid) {
boolean[][] visited = createVisitGrid(grid);
int res = 0;
for (int row = 0; row < grid.length; row++)
for (int col = 0; col < grid[row].length; col++)
if (!visited[row][col])
res = Math.max(res, dfs(grid, visited, grid[row][col], row, col));
return res;
}
private static int dfs(int[][] grid, boolean[][] visited, int expected, int row, int col) {
if (row < 0 || row >= grid.length)
return 0;
if (col < 0 || col >= grid[row].length)
return 0;
if (visited[row][col] || grid[row][col] != expected)
return 0;
visited[row][col] = true;
int depth = 1;
depth += dfs(grid, visited, expected, row, col - 1);
depth += dfs(grid, visited, expected, row, col + 1);
depth += dfs(grid, visited, expected, row - 1, col);
depth += dfs(grid, visited, expected, row + 1, col);
return depth;
}
private static boolean[][] createVisitGrid(int[][] grid) {
boolean[][] visit = new boolean[grid.length][];
for (int row = 0; row < grid.length; row++)
visit[row] = new boolean[grid[row].length];
return visit;
}

I need help declaring an array in java

public class matrix {
public static void main (String[] args) {
int[][] matrix = Array();
}
}
You need a count for each row for all columns and vice versa.
As you count upto 1 a boolean suffices: having found a non-zero element.
Instead of for row/for col and for col/for row which is a non space consuming fine algorith you could have done:
public static boolean isGPM(int [][] matrix) {
boolean[] rowNonZero = new boolean[matrix.length];
boolean[] colNonZero = new boolean[matrix[0].length];
for (int row = 0; row < matrix.length; row++) {
for (int col = 0; col < matrix[0].length; col++) {
if (matrix[row][col] != 0) {
if (rowNonZero[row] || colNonZero[col]) {
return false;
}
rowNonZero[row] = true;
colNonZero[col] = true;
}
}
}
return true;
}
Above an array for rowNonZero is not needed as you see.
Your version would be:
public static boolean isGPM(int [][] matrix) {
for (int row = 0; row < matrix.length; row++) {
boolean nonZero = false;
for (int col = 0; col < matrix[0].length; col++) {
if (matrix[row][col] != 0) {
if (nonZero) {
return false;
}
nonZero = true;
}
}
}
for (int col = 0; col < matrix[0].length; col++) {
boolean nonZero = false;
for (int row = 0; row < matrix.length; row++) {
if (matrix[row][col] != 0) {
if (nonZero) {
return false;
}
nonZero = true;
}
}
}
return true;
}
Since my reputation is too low to comment I'll post an answer. In isGPM function in your loops when you check if count/sum is not equal to 1, in your first iteration it is always going to be 0 and return false, unless there is a number that is different from 0 on the first position in array.
The way I'd dodge this is to do it like this:
int count = 0;
for(int row = 0; row < matrix.length; row++) {
for(int col = 0; col < matrix[0].length; col++)
if (matrix[row][col] != 0) {
count++;
}
}
if (count != 1)
return false;
You just move out the variable declaration of count from for loop and after the loop is finished you do the check. You can do the same thing for your other loop in the function.

algorithm for largest island in a given matrix

Given a 2 X 2 matrix, return different island sizes that is possible
For example, the following matrix should return [5, 7].
1 0 0 0 1
1 1 1 1 1
0 0 0 0 0
1 1 1 1 1
This is fairly straightforward problem. I am using a boolean visited matrix of same size and traverse the matrix in DFS fashion. I have implemented it here. for some reason, I am getting output as [1]. I tried debugging but my mind stopped working now. I am missing something silly I believe.
public class IslandConnectedCell {
public static void main(String[] args) {
int[][] input = {
{1,0,0,0,1},
{1,1,1,1,1},
{0,0,0,0,0},
{1,1,0,1,1}
};
dfsIsland(input);
}
public static void dfsIsland(int[][] input) {
int rows = input.length;
int cols = input[0].length;
List<Integer> countList = new ArrayList<>();
boolean visited[][] = new boolean[rows][cols];
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; cols++) {
if (input[row][col] == 1 && !visited[row][col]) {
int count = mark(row, col, input, visited, rows, cols, 0);
countList.add(count);
}
}
}
System.out.println(countList);
}
public static int mark(int row, int col, int[][] input, boolean[][] visited, int rows, int cols, int count) {
if (row >= rows || row < 0 || col >= cols || col < 0) {
return 0;
}
if (input[row][col] == 0 || visited[row][col]) {
return 0;
}
visited[row][col] = true;
count+=1;
for (int i = row - 1; i <= row + 1; i++) {
for (int j = col - 1; j <= col + 1; j++) {
if (i != row || j != col) {
mark(i, j, input, visited, rows, cols, count);
}
}
}
return count;
}
}
There are two errors in your code.
See comment by Mick for first error:
One obvious problem in dfsIsland() is at least that for (int col = 0; col < cols; cols++) should probably be for (int col = 0; col < cols; col++) instead (maybe even better to use the common i and j for the row/col indices).
Second error is your use of count in the mark method, most glaringly the lack of using the return value in the recursive call. Remember, Java is pass-by-value.
Hint: I suggest you remove count as a parameter.
Once you fix the errors, output will be:
[7, 2, 2]
public class IslandConnectedCell {
public static void main(String... args) {
int[][] board = { {1,0,0,0,1},
{1,1,1,1,1},
{0,0,0,0,0},
{1,1,0,1,1} };
System.out.println(new IslandConnectedCell(board).getIslandSizes());
}
private final int[][] board;
private final int rows;
private final int cols;
public IslandConnectedCell(int[][] board) {
this.board = board;
this.rows = board.length;
this.cols = board[0].length;
}
public List<Integer> getIslandSizes() {
boolean visited[][] = new boolean[this.rows][this.cols];
List<Integer> countList = new ArrayList<>();
for (int row = 0; row < this.rows; row++)
for (int col = 0; col < this.cols; col++)
if (this.board[row][col] == 1 && ! visited[row][col])
countList.add(mark(row, col, visited));
return countList;
}
private int mark(int row, int col, boolean[][] visited) {
if (row >= this.rows || row < 0 || col >= this.cols || col < 0 || this.board[row][col] == 0 || visited[row][col])
return 0;
visited[row][col] = true;
int count = 1;
for (int r = -1; r <= 1; r++)
for (int c = -1; c <= 1; c++)
if (r != 0 || c != 0)
count += mark(row + r, col + c, visited);
return count;
}
}
UPDATE
To get the desired output of [7, 4] (original question), the board would need to use horizontal wraparound, so the two small islands on the bottom line becomes a single larger island.
That is easily accomplished by modifying one line of code to wraparound the column index using the % modulus operator:
count += mark(row + r, (col + c + this.cols) % this.cols, visited);

Game of Life, java objects

On my program for java programming is not running right. My professor had us download a console.java to help use make a console to display our outputs of the program. I think the program is getting stuck when I am calling the update method and checkCells. My professor said that calling matrix.length for both rows and columns is incorrect but I'm stumped on how to call columns if I am not using matrix.length.
Any input is appreciated
import java.util.*;
public class Life {
private int birthLow = 0;
private int birthHigh = 0;
private int liveLow = 0;
private int liveHigh = 0;
private boolean[][] matrix;
public Life(long seed, int rows, int cols, int birthLow2, int birthHigh2, int liveLow2, int liveHigh2) {
boolean initalMatrix[][] = new boolean[rows][cols];
seedArray(initalMatrix, rows, cols, seed);
birthLow = birthLow2;
birthHigh = birthHigh2;
liveLow = liveLow2;
liveHigh = liveHigh2;
matrix = initalMatrix;
if ((rows < 1) && (cols < 1)) {
throw new IllegalArgumentException("Rows must be positive, not " + rows);
}
if ((rows > 9) && (cols < 9)) {
throw new IllegalArgumentException("Rows and cols cant go over 9, not " + rows + cols);
}
if (birthLow < 1 || (birthHigh > 9) || (liveLow < 1) || (liveHigh > 9)) {
throw new IllegalArgumentException("birth rates can not be below 1 or above 9 " + birthLow + birthHigh);
}
}
public boolean[][] world() {
boolean[][] matrixClone = matrix.clone();
for (int row = 0; row < matrix.length; row++) {
matrixClone[row] = matrix[row].clone();
}
return matrixClone;
}
public void update() {
matrix = checkCells(matrix, matrix.length, matrix.length, birthLow, birthHigh, liveLow, liveHigh);
}
public static void seedArray(boolean[][] matrix, int rows, int cols, long seed) {
// generates a random seed to fill the matrix
Random s = new Random(seed);
for (int r = 1; r < rows - 1; r++) {
for (int c = 1; c < cols - 1; c++) {
boolean x = s.nextBoolean();
matrix[r][c] = x;
}
}
}
public static void printBoard(boolean[][] matrix, int rows, int cols) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (matrix[r][c] == false && c == 0) {
System.out.print("- ");
} else if (matrix[r][c] == false && c > 0) {
System.out.print("- ");
} else if (matrix[r][c] == true) {
System.out.print("# ");
}
}
System.out.println();
}
System.out.println();
}
public static boolean[][] checkCells(boolean[][] matrix, int rows, int cols, int birthLow, int birthHigh,
int liveLow, int liveHigh) {
// clones matrix board
boolean[][] matrixClone = matrix.clone();
for (int row = 0; row < matrix.length; row++) {
matrixClone[row] = matrix[row].clone();
}
// determines if the living cell is going to live or die
for (int r = 1; r < rows; r++) {
for (int c = 1; c < cols; c++) {
if (neighbors(matrixClone, r, c) < liveLow || neighbors(matrixClone, r, c) > liveHigh || c == 0
|| r == 0 || c == cols - 1 || r == rows - 1) {
matrix[r][c] = false;
} else if (neighbors(matrixClone, r, c) >= birthLow && neighbors(matrixClone, r, c) <= birthHigh) {
matrix[r][c] = true;
}
}
}
return matrixClone;
}
public static int neighbors(boolean[][] matrixClone, int r, int c) {
int neighbors = 0;
// checks all neighbors for life or death
for (int rn = (r - 1); rn <= (r + 1); rn++) {
for (int cn = (c - 1); cn <= (c + 1); cn++) {
try {
if (matrixClone[rn][cn] == true) {
neighbors++;
}
// catches the array if it checks out the perimeter
} catch (ArrayIndexOutOfBoundsException f) {
continue;
}
}
}
return neighbors;
}
}
Don't use matrix.length for columns. You already know that. The reason is that it gives you the number of rows. Instead, just save the values of row and col and use them.
One way to do that is to make them fields, and initialize them in your constructor.
Do not initialize a random boolean[][] called initialMatrix. Instead, initialize the boolean[][] matrix that you have in the fields up above (matrix = new boolean[rows][cols]). Then for seedArray, call seedArray(matrix, rows, cols, seed).
Finally, in the update() method, do not use matrix.length, but rather rows and cols.

Categories