数独简易算法
package cn.tiger.funny;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 计算数独的所有解
* @author jyuan
*
*/
public class Sudoku {
private final Integer[] numbers = {1,2,3,4,5,6,7,8,9};
private List<Integer[][]> answer = new ArrayList<Integer[][]>();
/**
* 获取数独的所有解
* @param squared 数独
* @return 数独的所有解
*/
public List<Integer[][]> calculate(Integer[][] squared) {
long start = System.currentTimeMillis();
startCalculate(squared);
long end = System.currentTimeMillis();
System.out.println("take times:" + (end-start) + "ms.");
print();
return answer;
}
/**
* 获得两个数组交集
* @param arr1
* @param arr2
* @return 两个数组交集
*/
public Integer[] getB(Integer[] arr1, Integer[] arr2) {
Set<Integer> set1 = new HashSet<Integer>(Arrays.asList(arr1));
Set<Integer> set2 = new HashSet<Integer>(Arrays.asList(arr2));
set1.addAll(set2);
Integer[] result = {};
return set1.toArray(result);
}
/**
* 通过尝试所有可能性获得解
* @param squared 数独
*/
private void startCalculate(Integer[][] squared) {
for (int i = 0; i < squared.length; i++) {
for (int j = 0; j < squared[0].length; j++) {
if(i == squared.length-1 && j == squared.length-1 && squared[i][j] != 0) {
Integer[][] copy = new Integer[9][9];
for (int iLength = 0 ; iLength < 9; iLength++) {
for (int jLength = 0 ; jLength < 9; jLength++) {
copy[iLength][jLength] = squared[iLength][jLength];
}
}
answer.add(copy);
}
if (squared[i][j] != 0) {
continue;
} else {
for (int number : numbers) {
if(getUsedInIndex_x(squared, i).contains(number)
|| getUsedInIndex_y(squared, j).contains(number)
|| getUsedInSquared(squared, i, j).contains(number)) {
if(number==9) {
return;
}
continue;
} else {
squared[i][j] = number;
startCalculate(squared);
squared[i][j] = 0;
if(number==9) {
return;
}
}
}
}
}
}
}
/**
* 获得当前小九格中所有存在的数字
* @param squared 数独
* @param index_x 当前位置的x坐标
* @param index_y 当前位置的y坐标
* @return 当前小九格中所有存在的数字Set集合
*/
private Set<Integer> getUsedInSquared(Integer[][] squared, int index_x, int index_y) {
int smallSquared = getSmallSquared(index_x, index_y);
switch (smallSquared) {
case 1: {
return getUsedInSquaredVisCore(squared, 1, 1);
}
case 2: {
return getUsedInSquaredVisCore(squared, 1, 4);
}
case 3: {
return getUsedInSquaredVisCore(squared, 1, 7);
}
case 4: {
return getUsedInSquaredVisCore(squared, 4, 1);
}
case 5: {
return getUsedInSquaredVisCore(squared, 4, 4);
}
case 6: {
return getUsedInSquaredVisCore(squared, 4, 7);
}
case 7: {
return getUsedInSquaredVisCore(squared, 7, 1);
}
case 8: {
return getUsedInSquaredVisCore(squared, 7, 4);
}
case 9: {
return getUsedInSquaredVisCore(squared, 7, 7);
}
default:
throw new IllegalArgumentException("Unexpected value: " + smallSquared);
}
}
/**
* 获得当前行的所有数字
* @param squared 数独
* @param index_x 当前位置的x坐标
* @return 当前行的所有数字Set集合
*/
private Set<Integer> getUsedInIndex_x(Integer[][] squared, int index_x) {
Set<Integer> usedInIndex_x = new HashSet<Integer>();
for (int i = 0; i < squared[index_x].length; i++) {
if (squared[index_x][i] != 0) {
usedInIndex_x.add(squared[index_x][i]);
}
}
return usedInIndex_x;
}
/** 当前列的所有数字
* 获得当前列的所有数字
* @param squared 数独
* @param index_y 当前位置的y坐标
* @return 当前列的所有数字Set集合
*/
private Set<Integer> getUsedInIndex_y(Integer[][] squared, int index_y) {
Set<Integer> usedInIndex_y = new HashSet<Integer>();
for (int i = 0; i < squared.length; i++) {
if (squared[i][index_y] != 0) {
usedInIndex_y.add(squared[i][index_y]);
}
}
return usedInIndex_y;
}
/**
* 获得当前位置的小九格,按1-9排序
* @param index_x 当前位置的x坐标
* @param index_y 当前位置的y坐标
* @return 当前小九格对应的整数
*/
private int getSmallSquared(int index_x, int index_y) {
Integer[] xSquared = getSmallSquaredViaIndex_X(index_x);
Integer[] ySquared = getSmallSquaredViaIndex_Y(index_y);
for (int i : xSquared) {
for (int j : ySquared) {
if(i == j) {
return i;
}
}
}
throw new IllegalArgumentException("Unexpected value: " + index_x + " and " + index_y);
}
/**
* 获得当前位置对应的一列小九格,小九格按1-9排序
* @param index 当前位置的y坐标
* @return 返回三个整数数组
*/
private Integer[] getSmallSquaredViaIndex_Y(int index) {
switch (index) {
case 0:
case 1:
case 2: {
return new Integer[] {1, 4, 7};
}
case 3:
case 4:
case 5: {
return new Integer[] {2, 5, 8};
}
case 6:
case 7:
case 8: {
return new Integer[] {3, 6, 9};
}
default:
throw new IllegalArgumentException("Unexpected value: " + index);
}
}
/**
* 获得当前位置对应的一行小九格,小九格按1-9排序
* @param index 当前位置的x坐标
* @return 返回三个整数数组
*/
private Integer[] getSmallSquaredViaIndex_X(int index) {
switch (index) {
case 0:
case 1:
case 2: {
return new Integer[] {1, 2, 3};
}
case 3:
case 4:
case 5: {
return new Integer[] {4, 5, 6};
}
case 6:
case 7:
case 8: {
return new Integer[] {7, 8, 9};
}
default:
throw new IllegalArgumentException("Unexpected value: " + index);
}
}
/**
* 获得当前小九格中所有存在的数字
* @param squared 数独
* @param index_x 小九格中心位置x坐标
* @param index_y 小九格中心位置y坐标
* @return
*/
private Set<Integer> getUsedInSquaredVisCore(Integer[][] squared, int index_x, int index_y) {
Set<Integer> usedInSquared = new HashSet<Integer>();
for (int i = index_x-1; i <= index_x+1; i++) {
for (int j = index_y-1; j <= index_y+1; j++) {
if(squared[i][j] != 0) {
usedInSquared.add(squared[i][j]);
}
}
}
return usedInSquared;
}
/**
* 答应当前数独
* @param squared 数独
*/
private void print() {
System.out.println("*********************************************");
for (Integer[][] squared : answer) {
System.out.println("------answer------");
for (int x = 0 ; x < squared.length; x ++) {
for (int y = 0 ; y < squared[0].length; y++) {
System.out.print(squared[x][y] + " ");;
}
System.out.println();
}
}
}
public static void main(String[] args) {
Integer[][] in = new Integer[][] {
{8, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 3, 6, 0, 0, 0, 0, 0},
{0, 7, 0, 0, 9, 0, 2, 0, 0},
{0, 5, 0, 0, 0, 7, 0, 0, 0},
{0, 0, 0, 0, 4, 5, 7, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 3, 0},
{0, 0, 1, 0, 0, 0, 0, 6, 8},
{0, 0, 8, 5, 0, 0, 0, 1, 0},
{0, 9, 0, 0, 0, 0, 4, 0, 0}
};
Sudoku sudoku = new Sudoku();
sudoku.calculate(in);
}
}
耗时3257ms. 效率相比之前较低,之前基本可在1s内解决。

浙公网安备 33010602011771号