Getting an out of bounds exception but do not understand why. My recursive function calls itself each time removing an item from the array list till its empty. Once its empty the row should be filled and then we add the values back to the list. I think on the final element it throws an exception because of the list length, it does not want to delete last element. Is there any way around this? Is there any chance it is a different error?
import java.util.Arrays;
import java.util.Collections;
import java.util.Random;
import java.util.*;
class Main {
public static void main(String[] args) {
int[][]board=new int[9][9];
Solver solve = new Solver();
ArrayList<Integer> choices = new ArrayList<>();
choices.addAll(Arrays.asList(1,2,3,4,5,6,7,8,9));
Collections.shuffle(choices);
for(int i = 0; i < 9; i++){
for(int j=0; j < 9; j++) {
solve.fill(board, choices, i, j);
}
}
}
}
class Solver {
public void fill(int board[][], ArrayList<Integer> choices, int
row, int col) {
int num = choices.remove(0);
if (isValid(board, row, col, num) == false) {
fill(board, choices, row, col);
} else
board[row][col] = num;
return;
}
public boolean isValid(int board[][], int row, int col, int num) {
if (checkRow(board, row, col, num) == true)
/*checkCol(board, row, col, num) == true)*/
/*checkSqr(board, row, col, num) == true*/
return true;
return false;
}
public boolean checkRow(int board[][], int row, int col, int num) {
boolean valid = true;
int i = 0;
while (i < 9) {
if (board[i][col] == num) {
return valid = false;
}
i++;
}
return valid;
}
expected result would be the board [][] being populated randomly according to the sudoku rules.
instead we get
Exception in thread "main" java.lang.IndexOutOfBoundsException:
Index 0 out of bounds for length 0
at Solver.fill(Solver.java:31)
at Main.main(Solver.java:22)
Make sure you still have an element before calling int num = choices.remove(0); you could use List.isEmpty() like
if (choices.isEmpty()) {
return;
}
int num = choices.remove(0);
Related
I have to find how many times a given string can be built from a 2D grid of letters:
To build the word, I can start anywhere then move from cell to cell in one of 3 directions:
a) same row, next column (right)
b) next row, same column (down)
c) next row, next column (diagonal right and down)
Example:
char[][] grid = {{'a', 'a'}, {'a', 'a'}};
String str = "aa";
output:
5
Explanation:
a) [0,0][0,1]
b) [0,0][1,0]
c) [1,0][1,1]
d) [0,1][1,1]
e) [0,0][1,1]
This is my code so far:
class Solution {
public boolean exist(char[][] grid, String str) {
int m=grid.length,n=grid[0].length;
boolean[][] visited=new boolean[m][n];
int result = 0;
for (int i=0;i< m;i++){
for (int j=0;j<n;j++){
if (dfs(grid,visited,i,j,0,str)){
result++;
}
}
}
return result;
}
private boolean dfs(char[][] grid, boolean[][] visited, int x, int y, int i, String str){
int m=grid.length,n=grid[0].length;
if (i==str.length()) return true;
if(x<0||x>=m||y<0||y>=n) return false;
if(visited[x][y]) return false;
if(grid[x][y]!=str.charAt(i)) return false;
int[][] dirs={{1,0},{0,1},{1,1}};
visited[x][y]=true;
for (int[] dir: dirs){
int x1=x+dir[0], y1=y+dir[1];
if (dfs(grid, visited, x1, y1, i+1, str)){
return true;
}
}
visited[x][y]=false;
return false;
}
}
For the sample input I mentioned above I am able to get result as 2 instead of 5.
How can I fix this?
Is there any other better approach?
Start at 0,0 work across the columns and down the rows.
Create a method boolean check(String word, int startRow, int startCol, int dRow, int dCol) it will return true if the word is found beginning at startRow,startCol incrementing the column by dCol and the row by dRow after finding each letter. It can return false immediately if the letter being checked doesn't match or if the row or column would be out of bounds.
Call it three times in the loop, first with dRow = 0 and dCol = 1, then with both set to 1, then with dRow = 1 and dCol = 0.
Name your methods better dfs is not a good name.
Here's my version, not exactly as described above. I've decided to return an int rather than a boolean so I can easily add the result to the total. I've hard-coded a grid of letters just to simplify the example.
public class FindWord {
static char [][] grid = {
{'b','a','d'},
{'o','a','k'},
{'d','a','d'}
};
static final int cols = grid[0].length;
static final int rows = grid.length;
public static void main(String[] args) {
countWords("bad");
countWords("dad");
countWords("oak");
countWords("bod");
countWords("bid");
countWords("aaa");
countWords("aa");
countWords("d");
}
private static void countWords(String word) {
int total = 0;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
total += find(word,r,c,0,1) // across
+ find(word,r,c,1,1) // diagonal
+ find(word,r,c,1,0); // down
}
}
System.out.println(total);
}
private static int find(String word, int row, int col, int dRow, int dCol) {
for (char letter : word.toCharArray()) {
if (row >= rows || col >= cols || grid[row][col] != letter)
return 0;
row += dRow;
col += dCol;
}
return 1;
}
}
You might notice that this example has a bug for one letter words. It counts one letter words 3 times because it considers the same starting position as across, diagonal, and down. That is easy to fix with a condition to only check the "across" case and not the other two if the word length is one. I'll leave it to you to make that adjustment.
This is the word search problem on leetcode. I've provided a picture below that explains it well. My approach consists of a DFS on each letter in the board (by iterating through a double for loop), I'm doing this so my dfs function can start from each letter and I can get all the different words.
I'm marking the nodes as visited by also passing in a boolean array, where the value is changed to true if I've seen that node and changed back to false if it didn't lead to a path. I think this is where I'm messing up. I'm not sure how to properly mark the nodes as visited here, and if I don't then I get an infinite loop.
When I run my program and print out the strings the dfs is building, I don't get all the possible strings. This is what I'm trying to figure out, how to get all the strings.
You can run the code in leetcode as well. Thank you!
class Solution {
public boolean exist(char[][] board, String word) {
if(board == null || word == null) {
return false;
}
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[i].length; j++) {
List<Character> tempList = new ArrayList<>();
tempList.add(board[i][j]);
boolean[][] tempBoard = new boolean[board.length][board[0].length];
if(wordExists(i, j, word, tempList, board, tempBoard)) {
return true;
}
else{
tempList.remove(tempList.size() - 1);
}
}
}
return false;
}
public static boolean wordExists(int sr, int sc, String word, List<Character> list, char[][] board, boolean[][] tempBoard) {
StringBuilder sb = new StringBuilder();
for(Character c : list) {
sb.append(c);
}
System.out.println(sb.toString());
if(word.equals(sb.toString())) {
return true;
}
final int[][] SHIFTS = {
{0,1},
{1,0},
{0,-1},
{-1,0}
};
tempBoard[sr][sc] = true;
for(int[] shift : SHIFTS) {
int row = sr + shift[0];
int col = sc + shift[1];
if(isValid(board, row, col, tempBoard)) {
list.add(board[row][col]);
if(wordExists(row, col, word, list, board, tempBoard)) {
return true;
}
tempBoard[sr][sc] = false;
list.remove(list.size() - 1);
}
}
return false;
}
public static boolean isValid(char[][] board, int row, int col, boolean[][] tempBoard) {
if(row >= 0 && row < board.length && col >= 0 && col < board[row].length && tempBoard[row][col] != true) {
return true;
}
return false;
}
}
I'm trying to create a Sudoku solver in Java, in general I'm new to programming and to Java. I don't really know how to handle this kind of errors.
I keep getting a stack overflow error.
I tried diffrent codes for it , none of them worked but anyways here is my latest one:
public class Sudoku {
private int[][] values;
private boolean [][] writable;
private static final int ZERO = 0;
private static final int SIZE = 9;
//just a normal constructor that sets which values are changeable and which aren't. only values equal to zero are changeable.
public Sudoku(int[][] values) {
this.values = new int[SIZE][SIZE];
for(int row = 0; row< SIZE ; row++)
{
for(int col = 0; col< SIZE; col++)
{
this.values[row][col] = values[row][col];
}
}
writable = new boolean[values.length][values[1].length];
for(int i = 0;i < writable.length;i++)
{
for(int j = 0; j<writable[1].length;j++)
{
if(values[i][j] == ZERO)
{
writable[i][j] = true;
}
}
}
}
public void setValues(int row,int col ,int value) //changes the value if the value was changeable.
{
if(writable[row][col])
{
values[row][col]= value;
}
}
public int getValue(int row,int col) {
return values[row][col];
}
public boolean isWritable(int row,int col)
{
return writable[row][col];
}
private boolean ConflictAtRow(int row , int num)
{
for(int i = 0;i < SIZE;i++)
if(getValue(row,i) == num)
return true;
return false;
}
private boolean ConflictAtCol(int col, int num)
{
for(int i = 0;i<SIZE;i++)
if(getValue(i,col) == num)
return true;
return false;
}
private boolean ConflictAtBox(int row, int col, int num)
{
int r = row - row %3;
int c = col - col %3;
for(int i = r;i<r+3;i++)
{
for(int j = c;j<c+3;j++)
{
if(getValue(i, j) == num && row != i && col != j)
return true;
}
}
return false;
}
private boolean ConflictAt(int row, int col, int num)
{
return ConflictAtBox(row, col, num) && ConflictAtCol(col,num) && ConflictAtRow(row, num); //line 108
}
public boolean solve(int row,int col)
{
int nextRow = (col < 8) ? row:row+1;
int nextCol = (col +1)%9;
for (row = nextRow; row < SIZE; row++) {
for (col = NextCol; col < SIZE; col++) {
if(isWritable(row,col))
{
for (int num = 1; num <= 9; num++) {
if(!ConflictAt(row,col,num)) //line 118
{
setValues(row,col,num);
if(solve(nextRow,nextCol)) //line 122
return true;
}
setValues(row,col,ZERO);
}
}return !ConflictAt(row,col,getValue(row,col)) &&
solve(nextRow,nextCol);;
}
}return true;
}
and when I run the solve() method I get the stack overflow error
Exception in thread "main" java.lang.StackOverflowError
at Sudoku.Sudoku.ConflictAt(Sudoku.java:108)
at Sudoku.Sudoku.solve(Sudoku.java:118)
at Sudoku.Sudoku.solve(Sudoku.java:122)
at Sudoku.Sudoku.solve(Sudoku.java:122)
at Sudoku.Sudoku.solve(Sudoku.java:122)
at Sudoku.Sudoku.solve(Sudoku.java:122)
and so on ......
Once the control enters the solve() method for the first time, and if all the if conditions evaluate to true up to line 122, you are calling the solve() method again.
The problem is, every time the control hits this method, it is as though it were executing it for the first time. Because there is no change in conditions (for loops always start at 0).
What this means is, the solve() method gets repeatedly called until the stack runs out of memory.
I'm trying to write a program that takes a Sudoku puzzle and solves it.
However, I'm running into a StackOverflow error at this line:
Move nMove = new Move(current.nextMove(current, sboard).i, current.nextMove(current, sboard).j);
It has a method isLegal that checks for whether the move is valid. If move is valid and the next move is also valid, it adds it to a stack. If it is valid but the next move is not, it should keep searching for a valid number.
Not sure what's causing it.
import java.util.Stack;
public class Board {
Stack<Move> stack = new Stack<Move>();
int boardSize = 9;
public int[][] sboard = {{2,0,0,3,9,5,7,1,6},
{5,7,1,0,2,8,3,0,9},
{9,3,0,7,0,1,0,8,2},
{6,8,2,0,3,9,1,0,4},
{3,5,9,1,7,4,6,2,8},
{7,1,0,8,6,0,9,0,3},
{8,6,0,4,1,7,2,9,5},
{1,9,5,2,8,6,4,3,7},
{4,2,0,0,0,0,8,6,1}};
public Board() {
//for every cell in board:
for (int i = 0; i < boardSize; i++) {
for (int j = 0; j < boardSize; j++) {
//get the value of each cell
int temp = getCell(i,j);
//if cell is empty:
if (temp == 0) {
//print out location of cell
System.out.print ("("+i+", "+j+") ");
//guess values for that cell
solve(i, j);
}
}
}
}
//places a value into specified cell
public void setCell(int value, int row, int col) {
sboard[row][col] = value;
}
//returns value contained at specified cell
public int getCell(int row, int col) {
return sboard[row][col];
}
//if value is legal, continue
public boolean isLegal(int value, int row, int col) {
int r = (row / boardSize) * boardSize;
int c = (col / boardSize) * boardSize;
for (int i = 0; i < boardSize; i++) {
for (int j = 0; j < boardSize; j++) {
if (value == getCell(i, col) || value == getCell(row, j)) {
return false;
}
}
}
return true;
}
//guesses values for empty cells
public boolean solve(int i, int j) {
//set location as current
Move current = new Move(i, j);
Move nMove = new Move(current.nextMove(current, sboard).i, current.nextMove(current, sboard).j);
//guesses values 1 through 9 that are legal
for (int k = 1; k <= 9; k++) {
//if a legal value is found and the next move is possible:
if(isLegal(k, i, j) && solve(nMove.i, nMove.j)) {
//add current to stack
stack.push(current);
//enter the value k into the cell
setCell(k, i, j);
//print new value
System.out.print(sboard[i][j]+"\n");
//return as true
return true;
}
else if (stack.empty()){
}
//if next move is not possible
else if(!solve(nMove.i, nMove.j)){
//remove last "solved" location from stack
stack.pop();
//solve last location again
solve(stack.peek());
}
}
return false;
}
public void solve(Move m) {
solve(m.i, m.j);
}
public static void main(String[] args) {
Board b = new Board();
}
};
class Move {
int i, j;
public Move(int i, int j) {
this.i = i;
this.j = j;
}
public int i() { return i;}
public int j() { return j;}
public Move nextMove(Move current, int[][] sboard){
for (int i = current.i; i < 9; i++) {
for (int j = current.j; j < 9; j++) {
//get the value of each cell
int temp = sboard[i][j];
if (temp == 0) {
return new Move(i, j);
}
}
}
return current;
}
};
For one, it seems redundant to me to have this function in the form current.nextMove(current, board). You can either make this function static, or remove the Move current parameter.
But taking a look at your solve(i, j) function, you essentially have this:
Assume sboard[i][j] = 0 (which it clearly does, in some cases, from your input).
Assume you call solve(i, j).
current will be new Move(i, j).
nMove will then also be new Move(i, j) (since in Move#nextMove,
you essentially say if sboard[i][j] == 0, which it does from step
1).
You will end up calling solve(nMove.i, nMove.j)
Since nMove.i == i and nMove.j == j, you are essentially calling solve(i, j) over again.
Since you're calling the same function with the same parameter, and you're not reaching any base case, you will end up with a stack overflow.
As you have defined an (explicit) stack, you should not call solve() recursively.
Just loop, pop a board, generate all valid next moves, see if one of them is a solution, and if not, push them on the stack.
(I couldn't find where you verify that the board is complete, but I am probably tired.)
Btw, the stack should probably be a Dequeue. I believe a stack is synchronized which slows down the code.
Hi can anyone tell me what im doing wrong here?
i want to check each subgrid for repeated values in a 9by 9 square.
my method works first by creating each subgrid a one dimensional array which can then check each row for each subgrid. and for it to go to each subgrid i provide its coordinates myself.
it checks the first grid 0,0 but does not check other subgrids for repeated values.
can anyone tell me what im doing wrong?
public class SudokuPlayer
{
private int [][] game;
public enum CellState { EMPTY, FIXED, PLAYED };
private CellState[][] gamestate;
private int [][] copy;
private static final int GRID_SIZE=9;
private boolean whichGameToReset;
private int len;
private int stateSize;
private int row;
private int col;
private boolean coordinates(int startX, int startY)
{
row=startX;
col=startY;
if(isBoxValid()==false)
{
return false;
}
return true;
}
public boolean check()
{
if(coordinates(0,0)==false)
{
return false;
}
if(coordinates(0,3)==false)
{
return false;
}
if(coordinates(0,6)==false)
{
return false;
}
if(coordinates(1,0)==false)
{
return false;
}
if( coordinates(1,3)==false)
{
return false;
}
if( coordinates(1,6)==false)
{
return false;
}
if(coordinates(2,0)==false)
{
return false;
}
if(coordinates(2,3)==false)
{
return false;
}
if(coordinates(2,6)==false)
{
return false;
}
return true;
}
private boolean isBoxValid()
{
int[] arrayCopy = new int[game.length];
int currentRow = (row/3)*3;
int currentCol = (col/3)*3;
int i = 0;
for ( int r =currentRow; r < 3; r++)
{
for( int c =currentCol; c < 3; c++)
{
arrayCopy[i] = game[r][c];
i++;
}
}
for ( int p =0; p < arrayCopy.length; p++)
{
for ( int j = p+1; j < arrayCopy.length; j++)
{
if ( arrayCopy[p] == arrayCopy[j] && arrayCopy[j]!=0)
{
return false;
}
}
}
return true;
}
}
The problem is in your isBoxValid() method. You are initializing r and c to be currentRow and currentCol, respectively, but you run the loop up to a hard coded value of 3, not 3+currentRow or 3+currentCol. When currentRow and currentCol are 0, it works fine, but for other numbers, not so much.
Oh, another thing that's nice about writing concise code: it's easier to see where your errors are. Take another look at the numbers you've hard-coded into check(): you're incrementing the columns by 3 and the rows by 1. That would be much easier to spot if you compressed it into a pair of for loops.