I wrote a program for the percolation problem for the Coursera Algorithms course. Everything seems to compile successfully, but when I run it in terminal, it just freezes and no output is shown. Is my performance just way too slow, or is there a bug somewhere in my code? Code is posted below, the arguments I use are n = 200 and 100 trials. Thank you so much in advance!
import edu.princeton.cs.algs4.WeightedQuickUnionUF;
public class Percolation {
private WeightedQuickUnionUF grid;
private WeightedQuickUnionUF grid2;
private boolean[] openSites;
private int numOpenSites, gridLength, topIndex, bottomIndex;
public Percolation(int n) {
// create n-by-n grid, with all sites blocked
if (n <= 0) {
throw new IllegalArgumentException();
}
int numNodes = (n * n) + 2;
grid = new WeightedQuickUnionUF(numNodes);
grid2 = new WeightedQuickUnionUF(numNodes);
openSites = new boolean[n * n];
numOpenSites = 0;
gridLength = n;
topIndex = n * n;
bottomIndex = n * n + 1;
}
public void open(int row, int col) { // open site (row, col) if it is not open already
//check if row and col are valid
if (row < 1 || row > gridLength || col < 1 || col > gridLength) {
throw new IndexOutOfBoundsException();
}
//if not open, then open
if (!isOpen(row, col)) {
openSite(row, col);
connectTopVirtualSite(row, col);
connectAdjacentSites(row, col);
connectBottomVirtualSite(row, col);
numOpenSites++;
}
}
private void openSite(int row, int col) {
int index = convertToIndex(row, col);
//set that site to true
openSites[index] = true;
}
private void connectTopVirtualSite(int row, int col) {
if (row == 1) {
grid.union(topIndex, convertToIndex(row, col));
grid2.union(topIndex, convertToIndex(row, col));
}
}
private void connectAdjacentSites(int row, int col) {
connectTop(row, col);
connectLeft(row, col);
connectRight(row, col);
connectBottom(row, col);
}
private void connectTop(int row, int col) {
if (row > 1 && isOpen(row - 1, col)) {
grid.union(convertToIndex(row - 1, col), convertToIndex(row, col));
grid2.union(convertToIndex(row - 1, col), convertToIndex(row, col));
}
}
private void connectLeft(int row, int col) {
if (col > 1 && isOpen(row, col - 1)) {
grid.union(convertToIndex(row, col - 1), convertToIndex(row, col));
grid2.union(convertToIndex(row, col - 1), convertToIndex(row, col));
}
}
private void connectRight(int row, int col) {
if (col < gridLength && isOpen(row, col + 1)) {
grid.union(convertToIndex(row, col), convertToIndex(row, col + 1));
grid2.union(convertToIndex(row, col), convertToIndex(row, col + 1));
}
}
private void connectBottom(int row, int col) {
if (row < gridLength && isOpen(row + 1, col)) {
grid.union(convertToIndex(row, col), convertToIndex(row + 1, col));
grid2.union(convertToIndex(row, col), convertToIndex(row + 1, col));
}
}
private void connectBottomVirtualSite(int row, int col) {
if (row == gridLength) {
grid2.union(convertToIndex(row, col), bottomIndex);
}
}
private int convertToIndex(int row, int col) {
return gridLength * (row - 1) + (col - 1);
}
public boolean isOpen(int row, int col) { // is site (row, col) open?
if (row < 1 || row > gridLength || col < 1 || col > gridLength) {
throw new IndexOutOfBoundsException();
}
return openSites[convertToIndex(row, col)];
}
public boolean isFull(int row, int col) { // is site (row, col) full?
if (row < 1 || row > gridLength || col < 1 || col > gridLength) {
throw new IndexOutOfBoundsException();
}
return grid.connected(convertToIndex(row, col), topIndex);
}
public int numberOfOpenSites() { // number of open sites
return numOpenSites;
}
public boolean percolates() { // does the system percolate?
return grid2.connected(topIndex, bottomIndex);
}
//public static void main(String[] args) // test client (optional)
}
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.StdStats;
import edu.princeton.cs.algs4.WeightedQuickUnionUF;
import static java.lang.Math.sqrt;
public class PercolationStats {
private double[] results;
public PercolationStats(int n, int trials) {
if (n <= 0 || trials <= 0) {
throw new IllegalArgumentException();
}
results = new double[trials];
//fill up results with the p values of every trial
runExperiments(n, trials);
}
private void runExperiments(int n, int trials) {
int row, col;
for (int i = 0; i < trials; i++) {
Percolation test = new Percolation(n);
while (!test.percolates()) {
//generate new random row and col
row = StdRandom.uniform(n - 1) + 1;
col = StdRandom.uniform(n - 1) + 1;
test.open(row, col);
}
results[i] = (double)(test.numberOfOpenSites()) / (n * n);
}
}
public double mean() {
//return sample mean of all the p values
return StdStats.mean(results);
}
public double stddev() {
//return sample standard deviation of percolation threshold
return StdStats.stddev(results);
}
public double confidenceLo() {
return mean() - ((1.96 * stddev()) / sqrt(results.length));
}
public double confidenceHi() {
return mean() + ((1.96 * stddev()) / sqrt(results.length));
}
public static void main(String[] args) {
PercolationStats test = new PercolationStats(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
System.out.println("mean = " + test.mean());
System.out.println("stddev = " + test.stddev());
System.out.println("95% confidence interval = [" + test.confidenceLo() + ", " + test.confidenceHi() + "]");
}
}
Related
I am working on a Percolation java program. I have implemented the following Percolation.java file and am running into an error when testing it with certain input files, as described below.
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.WeightedQuickUnionUF;
public class Percolation {
private int n;
private WeightedQuickUnionUF verify;
private WeightedQuickUnionUF solution;
private int sink;
private int source = 0;
private boolean[][] grid;
private int openSites = 0;
private int length;
// creates n-by-n grid, with all sites initially blocked
public Percolation(int n) {
if (n <= 0) {
throw new IllegalArgumentException();
}
this.length = n;
this.grid = new boolean[length][length];
this.sink = (length * length) + 1;
verify = new WeightedQuickUnionUF(length * length + 2);
solution = new WeightedQuickUnionUF(length * length + 2);
for (int i = 0; i < length; i++) {
verify.union(encode(0, i), source);
solution.union(encode(0, i), source);
}
for (int j = 0; j < length; j++) {
verify.union(encode(n - 1, j), sink);
}
}
// opens the site (row, col) if it is not open already
public void open(int row, int col) {
grid[row][col] = true;
openSites++;
if ((row - 1) >= 0 && isOpen(row - 1, col)) {
verify.union(encode(row, col), encode(row - 1, col));
solution.union(encode(row, col), encode(row - 1, col));
}
if ((row + 1) < length && isOpen(row + 1, col)) {
verify.union(encode(row, col), encode(row + 1, col));
solution.union(encode(row, col), encode(row + 1, col));
}
if ((col - 1) >= 0 && isOpen(row, col - 1)) {
verify.union(encode(row, col), encode(row, col - 1));
solution.union(encode(row, col), encode(row, col - 1));
}
if ((col + 1) < length && isOpen(row, col + 1)) {
verify.union(encode(row, col), encode(row, col + 1));
solution.union(encode(row, col), encode(row, col + 1));
}
}
// is the site (row, col) open?
public boolean isOpen(int row, int col) {
return grid[row][col];
}
// is the site (row, col) full?
public boolean isFull(int row, int col) {
return solution.find(source) == solution.find(encode(row, col));
}
// returns the number of open sites
public int numberOfOpenSites() {
return openSites;
}
// does the system percolate?
public boolean percolates() {
return verify.find(0) == verify.find(sink);
}
// An integer ID (1...n) for site (i, j).
private int encode(int row, int col) {
int number = length * row + 1 + col;
return number;
}
// unit testing (required)
public static void main(String[] args) {
String filename = args[0];
In in = new In(filename);
int n = in.readInt();
Percolation perc = new Percolation(n);
while (!in.isEmpty()) {
int i = in.readInt();
int j = in.readInt();
perc.open(i, j);
}
StdOut.println(perc.numberOfOpenSites() + " open sites");
if (perc.percolates()) {
StdOut.println("percolates");
}
else {
StdOut.println("does not percolate");
}
// Check if site (i, j) optionally specified on the command line
// is full.
if (args.length == 3) {
int i = Integer.parseInt(args[1]);
int j = Integer.parseInt(args[2]);
StdOut.println(perc.isFull(i, j));
}
}
}
However, when I test the code using certain input files, I receive error messages such as the following:
java.lang.ArrayIndexOutOfBoundsException: Index 8 out of bounds for length 8
Percolation.isOpen(Percolation.java:63)
TestPercolation.checkIsOpen(TestPercolation.java:122)
TestPercolation.checkIsOpen(TestPercolation.java:105)
TestPercolation.check(TestPercolation.java:177)
TestPercolation.checkFile(TestPercolation.java:198)
TestPercolation.test1(TestPercolation.java:659)
TestPercolation.main(TestPercolation.java:963)
java.lang.ArrayIndexOutOfBoundsException: Index 25 out of bounds for length 25
java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
What in my code could be causing this? In other words, where is the issue and how can I fix it?
I cannot get my write to file code working the error message- writeFile cannot be resolved. I a trying to write the board positions to a text file so the game can be saved. If the user chooses to save the game then it should call a new subroutine that will write the pieces to the file.
/*
* Skeleton program code for the AQA COMP1 Summer 2016 examination
* This code to be used in conjunction with the Preliminary Material
* written by the AQA Programmer Team
* Developed in the NetBeans 7.3.1. programming environment
* Additional classes AQAConsole2016, AQAReadTextFile2016 and
* AQAWriteTextFile2016 may be used.
*
* A package name may be chosen and private and public modifiers added -
* permission to make these changes to the Skeleton Program does not need
* to be obtained from AQA or the AQA Programmer
*/
import java.util.Random;
public class Aaa {
AQAConsole2016 console = new AQAConsole2016();
Random random = new Random();
int boardSize;
public Aaa() {
char choice;
String playerName;
// int boardSize;
boardSize = 6;
playerName = "";
do {
displayMenu();
choice = getMenuChoice(playerName);
switch (choice) {
case 'p' : playGame(playerName, boardSize);
break;
case 'e' : playerName = getPlayersName();
break;
case 'c' : boardSize = changeBoardSize();
break;
}
} while (choice != 'q');
}
void setUpGameBoard(char[][] board, int boardSize) {
for (int row = 1; row <= boardSize; row++) {
for (int column = 1; column <= boardSize; column++) {
if (row == (boardSize + 1) / 2 && column == (boardSize + 1) / 2 + 1 || column == (boardSize + 1) / 2 && row == (boardSize + 1) / 2 + 1) {
board[row][column] = 'C';
} else {
if (row == (boardSize + 1) / 2 + 1 && column == (boardSize + 1) / 2 + 1 || column == (boardSize + 1) / 2 && row == (boardSize + 1) / 2) {
board[row][column] = 'H';
} else {
board[row][column] = ' ';
}
}
}
}
}
int changeBoardSize() {
int boardSize;
do {
console.print("Enter a board size (between 4 and 9): ");
boardSize = console.readInteger("");
} while (!(boardSize >= 4 && boardSize <= 9));
return boardSize;
}
int getHumanPlayerMove(String playerName) {
int coordinates;
console.print(playerName + " enter the coordinates of the square where you want to place your piece: ");
coordinates = console.readInteger("");
return coordinates;
}
int getComputerPlayerMove(int boardSize) {
return ((random.nextInt(boardSize) + 1) * 10 + (random.nextInt(boardSize) + 1));
}
boolean gameOver(char[][] board, int boardSize) {
for (int row = 1; row <= boardSize; row++) {
for (int column = 1; column <= boardSize; column++) {
if (board[row][column] == ' ')
return false;
}
}
return true;
}
String getPlayersName() {
String playerName;
console.print("What is your name? ");
playerName = console.readLine();
return playerName;
}
boolean checkIfMoveIsValid(char[][] board, int move) {
int row;
int column;
boolean moveIsValid;
row = move % 10;
column = move / 10;
moveIsValid = false;
if (((row<=boardSize) &&(row>0)) && ((column<=boardSize) && (column>0))){
if (board[row][column] == ' ') {
moveIsValid = true;
}
}
return moveIsValid;
}
int getPlayerScore(char[][] board, int boardSize, char piece) {
int score;
score = 0;
for (int row = 1; row <= boardSize; row++) {
for (int column = 1; column <= boardSize; column++) {
if (board[row][column] == piece) {
score = score + 1;
}
}
}
return score;
}
boolean checkIfThereArePiecesToFlip(char[][] board, int boardSize, int startRow, int startColumn, int rowDirection, int columnDirection) {
int rowCount;
int columnCount;
boolean flipStillPossible;
boolean flipFound;
boolean opponentPieceFound;
rowCount = startRow + rowDirection;
columnCount = startColumn + columnDirection;
flipStillPossible = true;
flipFound = false;
opponentPieceFound = false;
while (rowCount <= boardSize && rowCount >= 1 && columnCount >= 1 && columnCount <= boardSize && flipStillPossible && !flipFound ) {
if (board[rowCount][columnCount] == ' ') {
flipStillPossible = false;
} else {
if (board[rowCount][columnCount] != board[startRow][startColumn]) {
opponentPieceFound = true;
} else {
if (board[rowCount][columnCount] == board[startRow][startColumn] && !opponentPieceFound) {
flipStillPossible = false;
} else {
flipFound = true;
}
}
}
rowCount = rowCount + rowDirection;
columnCount = columnCount + columnDirection;
}
return flipFound;
}
void flipOpponentPiecesInOneDirection(char[][] board, int boardSize, int startRow, int startColumn, int rowDirection, int columnDirection) {
int rowCount;
int columnCount;
boolean flipFound;
flipFound = checkIfThereArePiecesToFlip(board, boardSize, startRow, startColumn, rowDirection, columnDirection);
if (flipFound) {
rowCount = startRow + rowDirection;
columnCount = startColumn + columnDirection;
while (board[rowCount][columnCount] != ' ' && board[rowCount][columnCount] != board[startRow][startColumn]) {
if (board[rowCount][columnCount] == 'H') {
board[rowCount][columnCount] = 'C';
} else {
board[rowCount][columnCount] = 'H';
}
rowCount = rowCount + rowDirection;
columnCount = columnCount + columnDirection;
}
}
}
void makeMove(char[][] board, int boardSize, int move, boolean humanPlayersTurn) {
int row;
int column;
row = move % 10;
column = move / 10;
if (humanPlayersTurn) {
board[row][column] = 'H';
} else {
board[row][column] = 'C';
}
flipOpponentPiecesInOneDirection(board, boardSize, row, column, 1, 0);
flipOpponentPiecesInOneDirection(board, boardSize, row, column, -1, 0);
flipOpponentPiecesInOneDirection(board, boardSize, row, column, 0, 1);
flipOpponentPiecesInOneDirection(board, boardSize, row, column, 0, -1);
}
void printLine(int boardSize) {
console.print(" ");
for (int count = 1; count <= boardSize * 2 - 1; count++) {
console.print("_");
}
console.println();
}
void displayGameBoard(char[][] board, int boardSize) {
console.println();
console.print(" ");
for (int column = 1; column <= boardSize; column++)
{
console.print(" ");
console.print(column);
}
console.println();
printLine(boardSize);
for (int row = 1; row <= boardSize; row++) {
console.print(row);
console.print(" ");
for (int column = 1; column <= boardSize; column++) {
console.print("|");
console.print(board[row][column]);
}
console.println("|");
printLine(boardSize);
console.println();
}
}
void displayMenu() {
console.println("(p)lay game");
console.println("(e)nter name");
console.println("(c)hange board size");
console.println("(q)uit");
console.println();
}
char getMenuChoice(String playerName) {
char choice;
console.print(playerName + " enter the letter of your chosen option: ");
choice = console.readChar();
return choice;
}
void playGame(String playerName, int boardSize) {
char[][] board = new char[boardSize + 1][boardSize + 1];
boolean humanPlayersTurn;
int move;
int humanPlayerScore;
int computerPlayerScore;
boolean moveIsValid;
setUpGameBoard(board, boardSize);
humanPlayersTurn = false;
int NoOfMoves=0;
do {
humanPlayersTurn = !humanPlayersTurn;
displayGameBoard(board, boardSize);
moveIsValid = false;
do {
if (humanPlayersTurn) {
move = getHumanPlayerMove(playerName);
} else {
move = getComputerPlayerMove(boardSize);
}
moveIsValid = checkIfMoveIsValid(board, move);
} while (!moveIsValid);
if (!humanPlayersTurn) {
NoOfMoves++;
console.println("The number of moves completed so far: " +NoOfMoves);
console.print("Press the Enter key and the computer will make its move");
console.readLine("");
}
makeMove(board, boardSize, move, humanPlayersTurn);
console.println();
String answer = console.readLine("Do you want to save the board? (y/n)");
if (answer.equalsIgnoreCase("y")){
writeBoard(board, boardSize);
console.println("Saved!");
}
} while (!gameOver(board, boardSize));
displayGameBoard(board, boardSize);
humanPlayerScore = getPlayerScore(board, boardSize, 'H');
computerPlayerScore = getPlayerScore(board, boardSize, 'C');
if (humanPlayerScore > computerPlayerScore) {
console.println("Well done, " + playerName + ", you have won the game!");
}
else {
if (humanPlayerScore == computerPlayerScore) {
console.println("that was a draw!");
} else {
console.println("The computer has won the game!");
}
console.println();
}
}
void writeBoard(char[][] board, int boardSize) {
String filename = "myFile.txt";
String piece = null;
writeFile.openFile(filename);
for(int row=1; row<=boardSize; row++){
for (int column = 1; column <= boardSize; column++) {
piece= Character.toString(board [row][column]);
writeFile.writeToTextFile(piece);
}
}
writeFile.closeFile();
}
public static void main(String[] args) {
new Aaa();
}
}
This Section contains the errors:
void writeBoard(char[][] board, int boardSize) {
String filename = "myFile.txt";
String piece = null;
writeFile.openFile(filename);
for(int row=1; row<=boardSize; row++){
for (int column = 1; column <= boardSize; column++) {
piece= Character.toString(board [row][column]);
writeFile.writeToTextFile(piece);
}
}
writeFile.closeFile();
}
The problematic section contains a variable named writeFile which can not be resolved. No where in the class Aaa that you have shared, neither this variable has been declared nor initialized with an instance of its type. So the method void writeBoard(char[][] board, int boardSize) gives compilation error.
From the usage of this variable it is clear that it belongs to a class which has following instance methods:
1) openFile(String filename)
2) writeToTextFile(String piece)
3) closeFile()
Please search the class which has the above methods and on finding create an instance of that as the first statement inside the method void writeBoard(char[][] board, int boardSize). Hope it helps.
I'm trying to create a strategy that will play against human or another strategy for the game Gomoku. I already have some kind of minimax function, although i don't quite understand how does it work and i also have a getscore function, which should send back the best score to minimax ? But the problem is that my getScore function does not recognize if there are 4 or 5 circles in a row/col/diagonally.
Here is my code:
public class JarmoStrategyV1 implements ComputerStrategy {
public static int Lrow = 0;
public static int Lcol = 0;
public static int Drow = 0;
public static int Dcol = 0;
public static final int E = 0;
public static final int X = 1; // black
public static final int O = -1; // white
public static final int WINSCORE = 100;
private static final int WINCOUNT = 5;
public Location getMove(SimpleBoard board, int player) {
// let's operate on 2-d array
int[][] b = board.getBoard();
System.out.println(getScore(b, player));
for (int row = 0; row < b.length; row++) {
for (int col = 0; col < b[0].length; col++) {
if (b[row][col] == SimpleBoard.EMPTY) {
// first empty location
return new Location(row, col);
}
}
}
return null;
}
#Override
public String getName() {
return "Student name";
}
public static int minimax(int[][] board, int player, int depth) {
if (getScore(board, player) == WINSCORE) {
//
return WINSCORE;
}
if (depth == 2) {
return getScore(board, player);
}
int max = Integer.MIN_VALUE;
if (player == -1){
max = Integer.MAX_VALUE;
}
System.out.println(max);
List<Location> possibleMoves = getPossibleMoves(board);
for (Location loc : possibleMoves) {
board[loc.getRow()][loc.getColumn()] = player;
int newplayer = 0 - player;
if(newplayer == 1){
int value = minimax(board, newplayer,depth + 1);
if(value < max) {
max = value;
}
}
if (newplayer == -1){
int value = minimax(board, newplayer, depth + 1);
if (value > max) {
max = value;
}
}
board[loc.getRow()][loc.getColumn()] = E;
}
return max;
}
public static int getScore(int[][] board, int muutuja) {
//int yks = 0;
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
if (board[row][col] == muutuja) {
if (row <= (board.length - 5)) {
if (col <= board.length && getCount(board, row, col, 0, 1, muutuja, WINCOUNT) >= (WINCOUNT - 1) && getCount(board, row, (col + 4), 0, 1, E, 1 ) >= 1) return 1; // - 4 in a row
if (row >= 1 && getCount(board, row, col, 1, 0, muutuja, WINCOUNT) >= (WINCOUNT -1) && getCount(board, (row - 1), col, 1, 0, E, 1) == 1) return 1;
if (getCount(board, row, col, 1, 0, muutuja, WINCOUNT) >= WINCOUNT) return 100; // | 5 in a row
if (col <= WINCOUNT && getCount(board, row, col, 1, 1, muutuja, WINCOUNT) >= WINCOUNT) return 100; // \
if (col >= WINCOUNT && getCount(board, row, col, 1, -1, muutuja, WINCOUNT) >= WINCOUNT) return 100; // /
}
if (col <= WINCOUNT && getCount(board, row, col, 0, 1, muutuja, WINCOUNT) >= WINCOUNT) return 100; // -
}
}
}
return 0;
}
public static int getCount(int[][] board, int row, int col, int rowd, int cold, int player, int test) {
int count = 0;
for (int i = 0; i < test; i++) {
if (board[row + i * rowd][col + i * cold] == player) count++;
else break;
}
return count;
}
public static ArrayList<Location> getPossibleMoves(int[][] board) {
ArrayList<Location> availableMoves = new ArrayList<Location>();
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
if (board[row][col] == E) {
availableMoves.add(new Location(row, col));
}
}
}
return availableMoves;
}
}
There seems to be some kind of a problem with getScore, when i run this code then i can only play for a while until my Gomoku app crashes.
If you want to try this out yourself then you can open this via Eclipse.
Download the project file: http://www68.zippyshare.com/v/feWl2QwC/file.html
Import it to eclipse projects/workspace.
And you also have to build path to those 2 jar files in lib folder.
NOTE: I can only edit files in gomoku.strategies package.
the stacktrace shows an exception. add debug print or run with debugger
java.lang.IllegalArgumentException: It's computer's turn, pass the player to makeMove()
at gomoku.Game.makeMove(Game.java:476)
I'm trying to write a backtracking code that will find the number of solutions in a NQueens problem. But I am getting stack overflows when I try to mark the diagonal grids where it is not safe to place a queen.
int dim;
private void recurseMark(int row, int col, boolean[][] board, boolean val) {
if(row >= dim || col >= dim || row < 0 || col < 0) return;
if(board[row][col]) return;
System.out.println("Row " + row + " Col " + col);
board[row][col] = val;
recurseMark(row+1, col-1, board, val);
recurseMark(row+1, col+1, board, val);
recurseMark(row-1, col+1, board, val);
recurseMark(row-1, col-1, board, val);
}
private void mark(int i, int k, boolean[][] board, boolean val) {
for(int j = 0; j < dim; j++) {
board[i][j] = val;
}
for(int j = 0; j < dim; j++) {
board[j][k] = val;
}
}
private int countQueens(int i, boolean[][] board) {
int count = 0;
if(i == dim) return 1;
for(int k = 0; k < dim; k++) {
if(!board[i][k]) {
board[i][k] = true;
mark(i, k, board, true);
System.out.println("Giving " + i + " " + k);
recurseMark(i, k, board, true);
count += countQueens(i+1, board);
recurseMark(i, k, board, false);
mark(i, k, board, false);
}
}
return count;
}
public int totalNQueens(int n) {
dim = n;
boolean[][] board = new boolean[n][n];
return countQueens(0, board);
}
public static void main(String[] args) {
NQueens nq = new NQueens();
System.out.println(nq.totalNQueens(2));
}
Any idea why it's overflowing for a small value of N?
Because your method recurses infinitely.
If the board is 8x8, then for example recurseMark(1, 1, board, false) calls recurseMark(2, 2, board, false) which calls recurseMark(1, 1, board, false) which calls recurseMark(2, 2, board, false) which calls recurseMark(1, 1, board, false) which ...
The problem is when recurseMark is called with false. Here is a correct recurseMark():
private void recurseMark(int row, int col, Boolean[][] board, Boolean val) {
if(row >= dim || col >= dim || row < 0 || col < 0) return;
if(board[row][col] != null) return;
System.out.println("Row " + row + " Col " + col);
board[row][col] = val;
recurseMark(row+1, col-1, board, val);
recurseMark(row+1, col+1, board, val);
recurseMark(row-1, col+1, board, val);
recurseMark(row-1, col-1, board, val);
}
What we have done here is to switch to a Boolean class rather than primitive boolean, and use the null case to represent "square not visited yet". As it was the "square not visited" state was "false".
I'm browsing through some sudoku solvers and I'm looking for one that utilizes backtracking, now I've found this code but I'm not really sure whether it uses backtracking or some other algorithm?
Help is appreciated.
abstract class SudoKiller {
private SudokuBoard sb; // Puzzle to solve;
public SudoKiller(SudokuBoard sb) {
this.sb = sb;
}
private boolean check(int num, int row, int col) {
int r = (row / sb.box_size) * sb.box_size;
int c = (col / sb.box_size) * sb.box_size;
for (int i = 0; i < sb.size; i++) {
if (sb.getCell(row, i) == num ||
sb.getCell(i, col) == num ||
sb.getCell(r + (i % sb.box_size), c + (i / sb.box_size)) == num) {
return false;
}
}
return true;
}
public boolean guess(int row, int col) {
int nextCol = (col + 1) % sb.size;
int nextRow = (nextCol == 0) ? row + 1 : row;
try {
if (sb.getCell(row, col) != sb.EMPTY)
return guess(nextRow, nextCol);
}
catch (ArrayIndexOutOfBoundsException e) {
return true;
}
for (int i = 1; i <= sb.size; i++) {
if (check(i, row, col)) {
sb.setCell(i, row, col);
if (guess(nextRow, nextCol)) {
return true;
}
}
}
sb.setCell(sb.EMPTY, row, col);
return false;
}
}
And if this is not backtracking, is there an easy way to "convert" to it?
The whole project can be found on the authors site.
Looks like it does backtracking via recursion.
Here we step forward:
sb.setCell(i, row, col);
and here we step backward:
sb.setCell(sb.EMPTY, row, col);