public class Solver {
public LinkedList<Sudoku> sudokus = new LinkedList<>();
public Solver() {
Sudoku current = null;
int count = 1;
try (BufferedReader br = new BufferedReader(new FileReader(new File("p096_sudoku.txt")))) {
for (String line; (line = br.readLine()) != null;) {
if (line.contains("Grid")) {
current = new Sudoku(count);
sudokus.add(current);
count++;
} else {
current.addLine(line);
}
}
} catch (IOException ex) {
Logger.getLogger(Solver.class.getName()).log(Level.SEVERE, null, ex);
}
}
/*
For debugging purposes
*/
public void SolveFirstPrint() {
int count = 0;
for (Sudoku s : sudokus) {
if (count == 0) {
s.lines = solve(s.lines);
if (s.lines != null) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(s.lines[i][j] + " ");
}
System.out.print("\n");
}
}
System.out.println();
}
count++;
}
}
public void SolveFirst() {
int count = 0;
for (Sudoku s : sudokus) {
if (count == 0) {
s.lines = solve(s.lines);
}
count++;
}
}
public void SolveAllPrint() {
for (Sudoku s : sudokus) {
s.lines = solve(s.lines);
}
for (Sudoku s : sudokus) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(s.lines[i][j] + " ");
}
System.out.print("\n");
}
System.out.println();
}
}
public void SolveAll() {
for (Sudoku s : sudokus) {
s.lines = solve(s.lines);
}
}
public static boolean check(int[] numbers) {
int[][] key = new int[2][numbers.length];
key[0] = numbers;
for (int i = 0; i < numbers.length; i++) {
key[1][i] = 0;
}
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] > 0) {
key[1][numbers[i] - 1]++;
}
}
boolean keycheck = false;
for (int i = 0; i < numbers.length; i++) {
if (key[1][i] > 1) {
keycheck = true;
break;
}
}
if (keycheck == true) {
return false;
} else {
return true;
}
}
public static boolean checkY(int[][] numbers, int y) {
int[] key = new int[numbers[y].length];
key = numbers[y];
return check(key);
}
public static boolean checkX(int[][] numbers, int x) {
int[] key = new int[numbers.length];
for (int i = 0; i < key.length; i++) {
key[i] = numbers[i][x];
}
return check(key);
}
public static boolean checkAll(int[][] numbers) {
//Check Y lijnen
for (int i = 0; i < numbers.length; i++) {
if (!checkY(numbers, i)) {
return false;
}
}
//Check X lijnen
for (int i = 0; i < numbers.length; i++) {
if (!checkX(numbers, i)) {
return false;
}
}
// Check of alle boxes nog kloppen
if (!checkSquare(numbers, 0, 2, 0, 2)) {
return false;
}
if (!checkSquare(numbers, 0, 2, 3, 5)) {
return false;
}
if (!checkSquare(numbers, 0, 2, 6, 8)) {
return false;
}
if (!checkSquare(numbers, 3, 5, 0, 2)) {
return false;
}
if (!checkSquare(numbers, 3, 5, 3, 5)) {
return false;
}
if (!checkSquare(numbers, 3, 5, 6, 8)) {
return false;
}
if (!checkSquare(numbers, 6, 8, 0, 2)) {
return false;
}
if (!checkSquare(numbers, 6, 8, 3, 5)) {
return false;
}
if (!checkSquare(numbers, 6, 8, 6, 8)) {
return false;
}
return true;
}
public static boolean checkSquare(int[][] numbers, int minX, int maxX, int minY, int maxY) {
Map<Integer, Integer> myMap = new HashMap<Integer, Integer>();
for (int j = minY; j < maxY +1; j++) {
for (int i = minX; i < maxX +1; i++) {
if (numbers[j][i] != 0) {
// Als de hashmap al dezelfde key heeft in deze box
if (myMap.containsKey(numbers[j][i])) {
// Kan het huidige nummer niet ingevoerd worden, dus false.
return false;
} else {
// Voeg nummer toe
myMap.put(numbers[j][i], 1);
}
}
}
}
return true;
}
public static boolean isValid(int[][] numbers) {
// Controlleer of er wel een grid van 9x9 is
if (numbers.length != 9 || numbers[0].length != 9) {
return false;
}
return (checkAll(numbers));
}
public static int[][] solve(int[][] numbers) {
int[] freeslot = getNext(numbers);
int f1 = freeslot[0];
int f2 = freeslot[1];
if (f1 == -1) {
return numbers;
}
numbers = recurseSolve(f1, f2, numbers);
return numbers;
}
public static int[][] recurseSolve(int yNR, int xNR, int[][] numbers) {
int[][] solved;
int[][] copy = new int[numbers.length][numbers[0].length];
for (int y = 0; y < numbers.length; y++) {
for (int z = 0; z < numbers[0].length; z++) {
copy[y][z] = numbers[y][z];
}
}
// Als t valid is doorgaan met next solven.
for (int i = 1; i < 10; i++) {
copy[yNR][xNR] = i;
boolean valide = isValid(copy);
if (valide) {
solved = solve(copy);
if (solved != null) {
return solved;
}
}
}
return null;
}
public static int[] getNext(int[][] numbers) {
int[] slot = {-1, -1};
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (numbers[i][j] == 0) {
slot[0] = i;
slot[1] = j;
return slot;
}
}
}
return slot;
}
public int EulerSum() {
int total = 0;
for (Sudoku sudoku : sudokus) {
total += sudoku.TopLeftNrs();
}
return total;
}
}
大家好!
我制作了上述数独求解器,但我遇到了问题。
我在下面进行了性能测试:
@Test
public void speedTest(){
solver = new Solver();
long tStart = System.currentTimeMillis();
solver.SolveFirst();
long tEnd = System.currentTimeMillis();
long tDelta = tEnd - tStart;
double elapsedSeconds = tDelta / 1000.0;
System.out.println("1 Sudoku: " +elapsedSeconds);
solver = new Solver();
long tStart2 = System.currentTimeMillis();
solver.SolveAll();
long tEnd2 = System.currentTimeMillis();
long tDelta2 = tEnd2 - tStart2;
double elapsedSeconds2 = tDelta2 / 1000.0;
System.out.println("50 Sudokus:"+elapsedSeconds2);
}
}
我得到了这些结果:
Testsuite:InputTest
1数独:0.014秒
50 Sudokus,尝试0:7.314秒
1个数据是如此之快,但是超过1对我的线性表现结果不是很有可能吗?
我应该使用的不是Int [] []吗?
提前致谢。
答案 0 :(得分:0)
我只看了你的代码/问题,但看起来你的解算器只是你的沼泽标准暴力数独求解器。看起来您正在从输入文件(未包括在内)中读取Sudokus。
一个潜在的原因是:并非所有50个sudokus都是相同的,因此需要不同的时间来解决。由于您的代码在输入文件中检查了一些神奇的“网格”。
数独的暴力解决方案不是解决数独的最有效方法;人们做出了某些投入,这些投入使他们需要很长时间。
无论如何,这是我的猜测。您可以在求解器中添加时序,以查看哪些时间需要很长时间。
你的solveFirst方法也不必要地迭代整个谜题集合;为什么不只是得到第一个并通过它来解决?