Sudoku Solver - Pass 1:
package personal.puzzles;
import java.util.HashSet;
import java.util.Set;
public class SudokuSolver {
Grid grid = new Grid();
public SudokuSolver(int[][] state) {
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
grid.setValue(new Coordinate(i, j, state[i][j]));
}
}
}
public boolean isInConsistentState() {
return grid.checkState();
}
public int[][] solveSudoku() {
getConsistentAssignment(grid);
return grid.getSudokuBoard();
}
private void getConsistentAssignment(Grid grid) {
while (grid.isNextUnassigned()) {
Coordinate next = grid.getNextUnassigned();
for (int i = 1; i <= 9; ++i) {
next.setValue(i);
grid.setValue(next);
if (grid.checkState()) {
getConsistentAssignment(grid);
return;
} else {
next.setValue(-1);
grid.setValue(next);
}
}
}
return;
}
public static class Grid {
int[][] x = new int[9][9];
public void setValue(Coordinate coordinate) {
x[coordinate.getX()][coordinate.getY()] = coordinate.getValue();
}
public int getValue(int i, int j) {
return x[i][j];
}
public boolean isNextUnassigned() {
for (int i = 0; i < 9; ++i)
for(int j = 0; j < 9; ++j)
if (x[i][j] == -1) {
return true;
}
return false;
}
public void print() {
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
System.out.print(x[i][j] + " ");
}
System.out.println();
}
}
public Coordinate getNextUnassigned() {
for (int i = 0; i < 9; ++i)
for(int j = 0; j < 9; ++j)
if (x[i][j] == -1) {
return new Coordinate(i, j, -1);
}
return null;
}
public boolean checkState() {
return checkColumns() && checkRows() && checkSubgrids();
}
private boolean checkColumns() {
for (int i = 0; i < 9; ++i) {
Set<Integer> columnValues = new HashSet<Integer>();
for (int j = 0; j < 9; ++j) {
if (columnValues.contains(x[i][j]))
return false;
if (x[i][j] != -1) columnValues.add(x[i][j]);
}
}
return true;
}
private boolean checkRows() {
for (int i = 0; i < 9; ++i) {
Set<Integer> rowValues = new HashSet<Integer>();
for (int j = 0; j < 9; ++j) {
if (rowValues.contains(x[j][i]))
return false;
if (x[j][i] != -1) rowValues.add(x[j][i]);
}
}
return true;
}
private boolean checkSubgrids() {
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
for (int k = 0; k < 9; ++k)
for (int l = 0; l < 9; ++l) {
if (Math.abs(i - k) == 2 && Math.abs(j - l) == 2 && i % 3 == 0 && j % 3 == 0) {
if (!checkForBlock(i, j, k, l))
return false;
}
}
return true;
}
private boolean checkForBlock(int x1, int y1, int x2, int y2) {
Set<Integer> blockValues = new HashSet<Integer>();;
for (int i = x1; i <= x2; ++i) {
for (int j = y1; j <= y2; ++j) {
if (blockValues.contains(x[i][j])) {
return false;
}
if (x[i][j] != -1) blockValues.add(x[i][j]);
}
}
return true;
}
public int[][] getSudokuBoard() {
return x;
}
}
public static class Coordinate {
int x, y, value;
Coordinate(int x, int y, int value) {
this.x = x;
this.y = y;
this.value = value;
}
public void setValue(int value) {
this.value = value;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getValue() {
return value;
}
}
public static void main(String[] args) {
int x[][] = {
{ -1, 3, 4, 6, 7, 8, 9, 1, 2},
{6, 7, 2, 1, 9, -1, 3, 4, 8},
{1, 9, 8, 3, 4, 2, 5, -1, 7},
{8, -1, 9, 7, 6, 1, 4, 2, 3},
{4, 2, 6, -1, 5, 3, -1, 9, 1},
{7, 1, 3, 9, 2, 4, 8, 5, 6},
{9, -1, 1, 5, 3, -1, 2, -1, 4},
{2, 8, 7, 4, 1, 9, 6, 3, 5},
{3, -1, 5, 2, -1, 6, 1, 7, 9},
};
SudokuSolver solver = new SudokuSolver(x);
int y[][] = solver.solveSudoku();
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
System.out.print(y[i][j] + " ");
}
System.out.println();
}
}
}