Sudoku-backtracking-Algorithmus
Zunächst werde ich erklären, dass dies eine Universität, die Zuordnung also ich verlange nicht, für jemanden zu schreiben, den code für mich, ich muss nur schon in die richtige Richtung. 🙂
Ok, also muss ich schreiben, einen Algorithmus zu lösen (lösbares) sudoku-Brett beliebiger Größe. Ich habe eine rekursive Funktion geschrieben, die kann lösen Sie jedes 9x9-Brett schnell (~1ms), aber wenn ich größere Platten (16x16), die schwer zu lösen Sie kämpfen.. ich habe ein test gehen für 20 Minuten und es kann nicht scheinen, um es zu lösen. Sie können lösen einfache 16x16 Rätsel oder sogar eine leere 16x16 Bord, so dass ich glaube nicht, dass es die Abmessungen sind das problem.. es ist eher der Algorithmus ist das problem, denke ich.
Sowieso, das ist die grundlegende Logik von meinem Programm..
- Ich habe ein 3D-Vektor, in dem die möglichen Werte, die ich jedes Quadrat
- Wenn ein Wert in ein Quadrat, dann ist es entfernt von den möglichen Werten der umgebenden Quadrat, Zeile und Spalte, dass es in
Dann meine lösen-Funktion ist im Grunde:
bool solve() {
if (there are no unfilled squares)
return true
if (the board is unsolvable - there are empty squares that have no possible values)
return false
while (there are empty squares)
{
int squaresFilled = fillSquaresWithOnlyOneChoice(); //this method updates the possible results vector whenever it fills a square
if (squaresFilled == 0)
break;
}
//exhausted all of the 'easy' squares (squares with only one possible choice), need to make a guess
while (there are empty squares that have choices left) {
find the square with the least number of choices
if (the square with the least number of choices has 0 choices)
return false; //not solvable.
remove that choice from the 3D vector (vector that has the choices for each square)
make a copy of the board and the 3D choices vector
fill the square with the choice
if (solve())
return true; //we're done
restore the board and choices vector
//the guess didn't work so keep looping and make a new guess with the restored board and choices -- the choice we just made has been removed though so it won't get made again.
}
return false; //can't go any further
}
Ist es etwas ineffizient zu diesem Thema? Gibt es eine Möglichkeit, ich könnte es besser funktionieren? Ich vermute, dass eine 16x16 board so lange dauert ist weil der Entscheidungsbaum für es ist so groß, dass für ein board, das nicht gefüllt, sehr stark. Es ist komisch, obwohl, weil ein 9x9-Brett lösen wird wirklich schnell.
Irgendwelche Ideen oder Anregungen wäre absolut genial. Wenn es irgendwelche Informationen, die ich vermisst habe, lassen Sie mich auch wissen!
- Ich schlage vor, Sie schauen in das Tanz links Algorithmus, es ist ein interessanter Ansatz zur Lösung dieser Art von Problemen. (Ganz anders als in Ihrem Ansatz aber.)
- Sie Algorithmus ist exponentiell, es ist also nicht verwunderlich, dass das hinzufügen einer zusätzlichen Schwierigkeitsgrad macht es für eine lange Zeit laufen. Durch Zufall (d.h. Laufzeit/Grad der Schwierigkeit des Problems + cpu/ram-Geschwindigkeit + Programm-design) sind Sie auf der Manschette. Was bedeutet, Ihr computer verarbeiten kann, e^f(81), aber nicht e^f(256). Nicht verwunderlich - wenn der erste ist 1ms, das bedeutet, dass dein computer verarbeitet, um e^f(81) op/ms, was bedeutet, dass es dauern wird, e^f(256) / e^f(81) ms für die zweite. Diese Zahl kann um e^170ms, das ist länger als das Universum existiert.
- f ist nur eine grobe Schätzung-Funktion, und die Schätzungen sollten als unterschätzen, denn ich habe nicht berücksichtigt, Basis ändern - Ihr Programm ist exponentiell mit einer Variante Basis als auch exponent (~9^81 theoretische Entscheidungen vs. ~16^256), und weil die größer Sie bekommen, verlieren Sie Geschwindigkeit, z.B. Zwischenspeichern.
- Ich würde gerne versuchen und Update mein original-Algorithmus vor völlig ändern, aber danke für den link, wenn ich verzweifelt könnte ich give it a shot! 🙂
- ah, das macht dann auch Sinn. Ich dachte wirklich, dass ich implementiert den Algorithmus gut aber ich denke, ich könnte brauchen, um vollständig zu überdenken es?
- Peter Norvig hat auch geschrieben, ein Stück auf die Lösung von Sudokus (nur 9x9 zwar nicht, aber vielleicht hilfreich sowieso): norvig.com/sudoku.html
Du musst angemeldet sein, um einen Kommentar abzugeben.
Zwischen dem ausfüllen der Quadrate mit nur eine Wahl und geht voll rekursiv auf dem board, es gibt mehr fortgeschrittene Aktionen, die Sie tun können. Lässt, dass "region" ist eine Zeile oder eine Spalte oder ein Quadrat region (3x3 oder 4x4).
Taktik 1
Wenn es die K-Quadrate in einer region, kann die nehmen nur identische K-Nummern (zum Beispiel zwei Quadrate, die kann nur 2 oder 5, oder-drei Quadrate, die kann nur 1, 7 und 8), dann alle anderen Plätze in dieser region kann nicht mit diesen bestimmten zahlen. Sie brauchen zu Durchlaufen jeder region, um Unkraut out "genommen" zahlen, so finden Sie, ein Quadrat mit nur eine logische Wahl (zum Beispiel den Dritten Platz mit 2, 4 und 5 logischerweise kann nur 4 oder vierten Platz mit 1, 3, 7 und 8 logisch kann nur 3).
Dieser hat bi-gelöst mit iteration, wenn Sie die folgenden Beispiel. Eine region hat Plätze mit diesem möglichen zahlen:
A: 1 2 3
B: 2 3
C: 2 3 4 5
D: 4 5
E: 4 5
Sollte der Algorithmus erkennt, dass die Quadrate D und E halten die zahlen 4 und 5, also 4 und 5 sind ausgeschlossen, von anderen Plätzen in der region. Der Algorithmus erkennt dann, dass die Plätze B und C halten den Nummern 2 und 3, und so schließt Sie von anderen Plätzen. Dies lässt Platz Ein, mit nur Nummer 1.
Taktik 2
Wenn eine Zahl kommt es in der region in nur einem Quadrat dann logisch, dass Platz, die Anzahl.
Taktik 3
Taktik 1 und 2 sind nur in besonderen Fällen von Taktik 3 mit K Plätzen nur mit K identischen Nummern. Sie können K-Quadrate und eine Menge von K zahlen und die K-Quadrate können, halten Sie eine beliebige Teilmenge der K zahlen. Betrachten Sie das folgende Beispiel einer region:
A: 1 2
B: 2 3
C: 1 3
D: 1 2 3 4
Quadrate A, B und C halten nur die zahlen 1, 2 und 3. Das ist K-K. das bedeutet, Dass jeder andere Platz kann nicht logisch halten diese zahlen, die Blätter von square D mit nur die Nummer 4.
Taktik 2 ist ein Spezialfall von Taktik 3, wenn K = N - 1.
Taktik 4
Nutzen Regionen überlappen. Angenommen, eine gewisse Anzahl vorhanden sein können, nur in bestimmten Plätzen der region. Wenn alle diese Felder gehören zu einem anderen überlappenden region, dann sollte diese Zahl sein, ausgeschlossen von allen anderen Plätzen in dieser region.
Taktik 5
Cache-Ergebnisse. Alle Regionen haben eine "dirty" - flag, das kennzeichnet, dass etwas in der region hat sich verändert aus der letzten Zeit, die region verarbeitet wird. Sie nicht haben, um Prozess-die region mit diesem flag nicht gesetzt ist.
Menschen verwenden alle diese Taktiken, und hasse es, zu erraten, eine Zahl, weil backtracking ist eine echte Schmerzen. Eigentlich ist die Schwierigkeit, ein Brett gemessen wird, mit der minimalen Anzahl von Vermutungen muss man machen, um das Brett zu lösen. Für die meisten "extreme" - boards eine gute Vermutung ist genug.
Schnell algorhitm für die Lösung von sudoku ist der Algorithmus X durch Donald Knuth. Sie repräsentieren Lösung des sudoku als exakte Abdeckung problem, und verwenden Sie dann Algorithmus X für die Lösung der EG-problem. Dann nutzen Sie DLX als effiziente Implementierung des Algorithmus X.
Gibt es tolle Erklärung auf wikipedia, wie die genaue Abdeckung für die Lösung von sudoku.
Ich kann Ihnen sagen, dass DLX ist extrem schnell fost Lösung des sudoku-in wird Häufig verwendet, in der schnellsten algorhitm.
http://www.setbb.com/phpbb/index.php?mforum=sudoku ist tolles forum, mit wahrscheinlich der besten sudoku-Programmierer.
Ich weiß nicht, ob Sie gesehen haben, diesen link vor.
Kann es auch nicht vergleichbar mit den dancing-links-Algorithmus Effizienz
als es nutzt naive form von backtracking. Trotzdem funktioniert es.
Sehen Sie, wenn es nützlich sein kann für Sie!
Kann auch sein, Sie können hinzufügen, ein paar Zeilen für die Lösung "easy" - Quadrate.
http://edwinchan.wordpress.com/2006/01/08/sudoku-solver-in-c-using-backtracking/
Du bist Algorithmus sieht gut aus. Das problem ist, dass Sie mit einer brute-force-Ansatz, und daher Ihre Laufzeit ist (Anzahl der Zeichen)^(Größe des Verwaltungsrats) - also für 9x9 es gibt 9^9=387420489 und für 16x16 die Laufzeit ist auf 16^16=18446744073709551616. Sie können den Unterschied sehen.
Versuchen Sie finden eine Dynamic programing Ansatz
Gibt es keine benötigen, um die Behandlung der Zellen mit nur einer möglichen Zahl als etwas besonderes. Sie besuchen schon die Zellen mit der geringsten Anzahl von Möglichkeiten ersten.
Auch: wenn Sie "entfernen, die Wahl aus dem 3D-Vektor", man könnte Sie auch entfernen Sie es von den anderen Zellen auf dem gleichen {Zeilen, Spalten,box}. Bitmasken werden wahrscheinlich passen in schön. (aber das backtracking wird ein bisschen härter)
als @ralu erwähnt, den schnellsten Algorithmus zu lösen Sudokus mithilfe von DLX. unten ist ein Programm, das ich schrieb in der Vergangenheit. kann es lösen 4*4 sudoku innerhalb von 1 Sekunde.
angenommen, die Eingabe ist wie:
u können einen Versuch haben 🙂