import java.util.HashSet;
import java.util.Set;
public class SudoKuRecursion {
private int[][] origin;
private int[][] result;
private boolean isResolved;
public SudoKuRecursion( final int[][] iS) {
origin = copySudoku(iS);
isResolved = false;
}
private int[][] copySudoku( final int[][] origin) {
int[][] dest;
if (origin.length != 9) {
throw new RuntimeException( "range error");
}
dest = new int[9][];
for ( int i = 0; i < 9; i++) {
if (origin[i].length != 9) {
throw new RuntimeException( "range error");
}
dest[i] = new int[9];
for ( int j = 0; j < 9; j++) {
dest[i][j] = origin[i][j];
}
}
return dest;
}
// 1=right here
// 0=maybe
// -1=wrong
private int check( final int[][] origin, final int x, final int y, final int value) {
if (origin.length > 9 || x < 0 || x > 8 || y < 0 || y > 8 || value < 1 || value > 9) {
throw new RuntimeException( "range");
}
int lx = x / 3;
lx = lx * 3;
int ly = y / 3;
ly = ly * 3;
Set<Integer> s = new HashSet<Integer>();
for ( int i = 0; i < 9; i++) {
if (i != y) {
if (origin[x][i] == value) {
return -1;
} else {
s.add(origin[x][i]);
}
}
if (i != x) {
if (origin[i][y] == value) {
return -1;
} else {
s.add(origin[i][y]);
}
}
int tx = lx + ( int) (i / 3);
int ty = ly + ( int) (i % 3);
if (tx != x && ty != y) {
if (origin[tx][ty] == value) {
return -1;
} else {
s.add(origin[tx][ty]);
}
}
}
s.remove(0);
if (s.size() == 8) {
return 1;
} else {
return 0;
}
}
private void printSuduku( final int[][] sudoku) {
System.out.println( "----------------------------------");
for ( int i = 0; i < 9; i++) {
for ( int j = 0; j < 9; j++) {
System.out.print(sudoku[i][j] + " ");
}
System.out.println();
}
}
public void printResult() {
if (isResolved) {
System.out.println( "original sudoku:");
printSuduku(origin);
System.out.println( "result:");
printSuduku(result);
} else {
System.out.println( "not resolved.");
}
}
private void verifySudoku( int[][] origin, final int x, final int y) {
if (origin[x][y] == 0) {
for ( int i = 1; i < 10; i++) {
int r = check(origin, x, y, i);
if (r == 1) {
origin[x][y] = i;
if (x == 8 && y == 8) {
result = copySudoku(origin);
isResolved = true;
break;
}
int nx = (y == 8 ? x + 1 : x);
int ny = (y == 8 ? 0 : y + 1);
verifySudoku(origin, nx, ny);
break;
} else if (r == 0) {
origin[x][y] = i;
int nx = (y == 8 ? x + 1 : x);
int ny = (y == 8 ? 0 : y + 1);
verifySudoku(origin, nx, ny);
}
}
origin[x][y] = 0;
} else {
if (x == 8 && y == 8) {
result = copySudoku(origin);
isResolved = true;
return;
}
int nx = (y == 8 ? x + 1 : x);
int ny = (y == 8 ? 0 : y + 1);
verifySudoku(origin, nx, ny);
}
}
public boolean resolve() {
verifySudoku(origin, 0, 0);
return isResolved;
}
public static void main(String[] args) {
int[][] sudoku = { { 0, 3, 7, 0, 0, 0, 0, 6, 0 }, { 6, 0, 9, 0, 0, 4, 8, 0, 0 }, { 8, 1, 0, 0, 6, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 5, 0, 0 }, { 1, 0, 0, 2, 4, 0, 6, 0, 9 },
{ 5, 0, 0, 6, 0, 0, 0, 4, 0 }, { 0, 0, 3, 0, 7, 0, 0, 0, 6 }, { 0, 0, 6, 1, 0, 9, 0, 2, 5 }, { 0, 0, 0, 0, 0, 6, 0, 0, 0 } };
SudoKuRecursion sr = new SudoKuRecursion(sudoku);
sr.resolve();
sr.printResult();
}
}