1 | package eu.hsrw.tr.prog.vl.arrays; |
---|
2 | |
---|
3 | /** |
---|
4 | * Löst 9x9 Sudokus mittels Brute Force und Backtracking: Durchprobieren von |
---|
5 | * oben links nach unten rechts |
---|
6 | * |
---|
7 | * @author Thomas Richter |
---|
8 | * |
---|
9 | */ |
---|
10 | public class SudokuSolverBF extends SudokuHelper { |
---|
11 | |
---|
12 | /** |
---|
13 | * Löst das übergebene 9x9 Sudoku mittels Brute Force und Backtracking: Es |
---|
14 | * wird mit dem Element oben links begonnen und dann spalten- und |
---|
15 | * zeilenweise nach rechts unten gearbeitet. Als erster Wert wird die 1 |
---|
16 | * versucht. Falls der Versuch einen Konflikt auslöst wird die Zahl immer |
---|
17 | * weiter erhöht bis entweder kein Konflikt mehr auftritt oder die Zahl 10 |
---|
18 | * erreicht wurde. Falls 10 erreicht wurde konnte kein passender Eintrag |
---|
19 | * gefunden werden, das Problem muss also schon weiter vorn liegen. Es wird |
---|
20 | * um ein Feld zurückgegangen und dort die nächsthöhere Zahl versucht. Ggf. |
---|
21 | * sind sehr viele Rücksprünge erforderlich, da viele Kombinationen |
---|
22 | * durchprobiert werden müssen. |
---|
23 | * |
---|
24 | * @param a |
---|
25 | * zu lösendes Sudoku als 9x9 Array |
---|
26 | * @return Informationen über die Anzahl der Rücksprünge und der |
---|
27 | * Schleifeneintritte |
---|
28 | */ |
---|
29 | public static String solve(int[][] a) { |
---|
30 | // wir beginnen oben links und gehen nach unten rechts durch |
---|
31 | // Nummer des Elements: 0..80 |
---|
32 | int element = 0; |
---|
33 | // zähle die Rücksprünge |
---|
34 | long rueckspruenge = 0; |
---|
35 | |
---|
36 | while (element <= 80) { |
---|
37 | // Zeile und Spalte aus der Nummer des Elements bestimmen |
---|
38 | int zeile = element / 9; |
---|
39 | int spalte = element % 9; |
---|
40 | |
---|
41 | // Es werden nur Elemente bearbeitet, die nicht negativ sind. |
---|
42 | // negative Zahlen sind die Startbelegung -> überspringen |
---|
43 | if (a[zeile][spalte] >= 0) { |
---|
44 | |
---|
45 | // Versuche, eine Zahl im Element a[zeile][spalte] einzubauen |
---|
46 | // Beginne mit der aktuellen Zahl + 1: anfangs 0 + 1 |
---|
47 | int zahl = a[zeile][spalte] + 1; |
---|
48 | |
---|
49 | // testen, ob die Zahl einen Sudoku-Fehler verursacht |
---|
50 | // bei Fehler: Zahl erhöhen |
---|
51 | while (!kandidatOK(a, zeile, spalte, zahl)) { |
---|
52 | loopCount++; |
---|
53 | |
---|
54 | zahl++; |
---|
55 | } |
---|
56 | |
---|
57 | // Warum sind wir aus der Schleife rausgekommen? |
---|
58 | if (zahl < 10) { |
---|
59 | // zahl < 10 hat keinen Fehler verursacht -> eintragen |
---|
60 | a[zeile][spalte] = zahl; |
---|
61 | // weiterrücken zum nächsten Element |
---|
62 | element++; |
---|
63 | |
---|
64 | } else { |
---|
65 | // zahl == 10 -> keine passende Zahl gefunden -> zurückgehen |
---|
66 | // Element auf 0 zurücksetzen damit der Test nicht verfälscht wird |
---|
67 | a[zeile][spalte] = 0; |
---|
68 | |
---|
69 | // Wir dürfen nicht auf ein Element mit negativem Eintrag |
---|
70 | // zurückspringen, da die negativen Zahlen die Startbelegung |
---|
71 | // kennzeichnen -> Zurück bis Inhalt nicht mehr negativ |
---|
72 | do { |
---|
73 | loopCount++; |
---|
74 | |
---|
75 | element--; |
---|
76 | rueckspruenge++; |
---|
77 | } while (a[element / 9][element % 9] < 0); |
---|
78 | } |
---|
79 | |
---|
80 | } else { |
---|
81 | // Zahl war negativ -> weiterrücken |
---|
82 | element++; |
---|
83 | } |
---|
84 | } |
---|
85 | // return rueckspruenge + ";" + loopCount; |
---|
86 | |
---|
87 | return "Rücksprünge: " + rueckspruenge + " --- LC: " + loopCount; |
---|
88 | } |
---|
89 | |
---|
90 | public static void main(String[] args) { |
---|
91 | |
---|
92 | int[][] sudoku = parseSudokuString(SudokuPuzzles.sExtreme2); |
---|
93 | |
---|
94 | printSudoku(sudoku); |
---|
95 | |
---|
96 | System.out.println(solve(sudoku)); |
---|
97 | |
---|
98 | printSudoku(sudoku); |
---|
99 | } |
---|
100 | } |
---|