From 8a5ae8c6402ee36f7adf3dcda0633dda65c520a2 Mon Sep 17 00:00:00 2001 From: Alexander Klein Date: Thu, 10 Sep 2026 23:21:38 +0200 Subject: [PATCH] Document solver roadmap in README --- README.md | 1 + ROADMAP.md | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 ROADMAP.md diff --git a/README.md b/README.md index 9a58cf2..a01fc41 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ nach Möglichkeit mit paketnahen `*_test.go`-Tests ergänzt werden. | `sudoku/` | Fassade, die Parser, Feld und Solver zu einem Spiel verbindet | | `data/` | Mitgelieferte Beispielrätsel samt eigener Herkunfts- und Lizenzhinweise | | `todo.md` | Offene technische Ideen und Aufgaben | +| [`ROADMAP.md`](ROADMAP.md) | Priorisierter Fahrplan bis zum stabilen Solver | Der Datenfluss der Demo ist: diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..3224a63 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,224 @@ +# Entwicklungsfahrplan + +Dieser Fahrplan führt das Projekt vom aktuellen Prototyp zu einem verlässlichen, +erklärbaren Sudoku-Löser. Die Reihenfolge ist absichtlich abhängigkeitsorientiert: +Neue Strategien bauen erst dann auf dem Solver auf, wenn Feldmodell, Änderungen +und Fortschrittserkennung korrekt und getestet sind. + +## Zielbild + +Das erste stabile Release soll: + +- klassische 9x9-Sudokus sicher einlesen und validieren, +- jeden Lösungsschritt deterministisch und nachvollziehbar protokollieren, +- einfache und mittlere Rätsel mit menschlichen Strategien lösen, +- bei Stillstand einen klaren Status statt eines Panic oder Endloslaufs liefern, +- über eine kleine CLI mit Datei, Standard-Eingabe oder direkter Rätselzeichenfolge + nutzbar sein und +- durch Unit-, Integrations- und Regressionstests abgesichert sein. + +Backtracking, DLX und sehr fortgeschrittene menschliche Strategien folgen auf +dieses Kern-Release. + +## Phase 0 – Lauffähige und getestete Basis (P0) + +Zuerst wird der bestehende Zustand stabilisiert. In dieser Phase werden keine +neuen Lösungsstrategien ergänzt. + +- Test-Helfer für kleine Felder und 9x9-Rätsel anlegen. +- Regressionstests für die aktuell bekannten Abstürze und Logikfehler schreiben. +- `Field.ForEachCell` so korrigieren, dass echte Zellen statt Kopien übergeben + werden. +- `Field.GetCell` gegen negative Indizes und `row == Rows` beziehungsweise + `column == Columns` absichern. +- die Zahlenausgabe in `Field.String` ohne fehlerhafte int-zu-string-Konvertierung + implementieren. +- doppelte oder widersprüchliche Änderungen aus überlappenden Zeilen, Spalten + und Blöcken verhindern; damit auch den Nil-Panic in `LastDigit` beseitigen. +- die beiden Slice-Iterationsfehler in `HiddenSingle` korrigieren: Kandidatenwerte + statt Indizes auswerten. +- in `Cell.RemoveNumber` die korrekte Aktion `ActionRemoveNumber` protokollieren. +- Nil-Eingaben bei Feld, Zelle, Position und Änderung kontrolliert als Fehler + behandeln. +- Solver-Fortschritt so erkennen, dass ein Schritt weder fälschlich Stillstand + meldet noch endlos wiederholt wird. + +Abgeschlossen, wenn: + +- `go test ./...` und `go vet ./...` erfolgreich sind, +- `go run .` das ausgewählte Beispiel ohne Panic beendet und +- die bekannten Fehler jeweils einen Regressionstest besitzen. + +## Phase 1 – Verlässliches Feldmodell (P0) + +- `field.Properties` beim Erzeugen prüfen: positive Dimensionen, passende + Blockaufteilung und exakt passende Zellmatrix. +- Zahlenbereich und Position jeder Zelle prüfen; leere Zellen bleiben als `0` + repräsentiert. +- `Part.IsSolved` für Zeilen, Spalten und Blöcke implementieren. +- `Field.IsValid` implementieren: keine Duplikate, nur erlaubte Werte und + konsistente Dimensionen. +- `Field.IsSolved` an Vollständigkeit **und** Validität koppeln. +- Kandidaten-Invarianten festlegen: sortiert, eindeutig, im gültigen Bereich und + niemals an bereits belegten Zellen. +- Änderungen atomar anwenden und validieren. Ungültige Änderungen sollen einen + Fehler zurückgeben und das Feld unverändert lassen. +- lesenden Zugriff auf Eigenschaften und Änderungshistorie anbieten, ohne + interne Slices veränderbar nach außen zu geben. +- allgemeine und 9x9-spezifische Darstellung trennen; `StringNotesForNumber` + implementieren oder bis zu einem echten Bedarf aus der API entfernen. + +Abgeschlossen, wenn gültige, ungültige, unvollständige und gelöste Felder in +Tabellentests eindeutig unterschieden werden und keine Mutation die +Feld-Invarianten umgehen kann. + +## Phase 2 – Robuste Parser- und Game-API (P0) + +- Parserfehler vereinheitlichen und mit Zeilennummer sowie fehlerhaftem Feld + anreichern. +- Puzzle-Bank-Datensätze strikt prüfen: Hash, 81 Ziffern, Rating, Whitespace, + LF/CRLF und leere Zeilen. +- bei einem Parse-Fehler keine teilweise eingelesene Ergebnisliste übernehmen; + wiederholte `Parse`-Aufrufe dürfen alte Ergebnisse nicht ungewollt anhängen. +- `GetField` so ändern, dass ein ungültiger Index einen Fehler liefert statt + eines leeren, später abstürzenden Felds. +- die fest kodierte Auswahl `GetField(2)` aus `sudoku.New` entfernen. Das + ausgewählte Feld soll explizit übergeben oder vom Aufrufer gewählt werden. +- zusätzlich einen einfachen Parser für eine 81-stellige Rätselzeichenfolge + bereitstellen; er eignet sich für CLI, Tests und externe Nutzung. +- die Ausgangsbelegung bereits beim Erzeugen eines `Game` validieren. + +Abgeschlossen, wenn fehlerhafte Eingaben ohne Panic verständliche Fehler liefern +und Parser sowie `Game` keine implizite Rätselauswahl mehr enthalten. + +## Phase 3 – Klare Solver-Architektur (P0/P1) + +- ein Solver-Interface definieren, das später menschlichen Solver, Backtracking + und DLX austauschbar macht. +- `Run(int) bool` durch eine aussagekräftige Schritt-API ersetzen, zum Beispiel + mit den Zuständen `Progress`, `Solved`, `Stuck`, `Invalid` und `Failed`. +- Konfiguration aus den ungenutzten `conf`-Feldern ableiten oder diese entfernen. +- Strategie-Reihenfolge, Wiederholungspunkt und `ApplyNext`/`ApplyAll` eindeutig + definieren. +- gefundene Änderungen vor dem Anwenden deduplizieren und auf Konflikte prüfen. +- Kandidaten nach jedem Zahlenschritt korrekt und deterministisch aktualisieren. +- Tippfehler in öffentlichen Namen (`InitStragies`, `TriggerdBy`) kontrolliert + migrieren und alle Aufrufer anpassen. +- Abbruch bei Stillstand, ungültigem Zustand und internem Fehler sauber durch + `sudoku.Game.Solve` reichen. + +Abgeschlossen, wenn derselbe Input stets dieselben Schritte erzeugt und jeder +Solverlauf genau einen überprüfbaren Endzustand besitzt. + +## Phase 4 – Menschlicher Basis-Solver (P1) + +Die Strategien werden in aufsteigender Komplexität implementiert. Jede Strategie +benötigt positive, negative und Konflikt-/Überlappungstests sowie mindestens ein +komplettes Beispielrätsel. + +1. Kandidaten erzeugen und pflegen (`Notes`) +2. `LastDigit` +3. `NakedSingle` +4. `HiddenSingle` +5. `NakedPair` und `NakedTriple` +6. `HiddenPair` und `HiddenTriple` +7. `LockedCandidateT1`, `LockedCandidateT2` und `LockedPair` + +Abgeschlossen, wenn die mitgelieferten einfachen und mittleren Beispieldaten +ohne Raten lösbar sind und jeder Schritt seine auslösende Strategie nennt. + +## Phase 5 – Erklärbarer Lösungsweg und Undo (P1) + +- Änderungen zu fachlichen Schritten gruppieren: eine Schlussfolgerung kann aus + einer gesetzten Zahl und mehreren entfernten Kandidaten bestehen. +- `GetSolutionPath` mit defensiven Kopien implementieren. +- pro Schritt Strategie, betroffene Zellen, alter/neuer Wert, Begründung und + optionale Markierungen speichern. +- `Mark` vollständig von außen lesbar und unabhängig von internen + `Change`-Zeigern gestalten. +- Undo/Redo auf Basis atomarer Schritte implementieren; `prevSolveStep` entweder + fertigstellen oder bis dahin entfernen. +- menschenlesbare Textausgabe und ein stabiles JSON-Format für Lösungswege + ergänzen. + +Abgeschlossen, wenn ein gelöstes Feld vollständig zum Ausgangszustand +zurückgesetzt und durch Wiederanwenden desselben Pfads identisch rekonstruiert +werden kann. + +## Phase 6 – Fortgeschrittene Strategien (P2) + +Erst nach stabiler Schritt- und Markierungslogik ergänzen: + +1. `XWing` +2. `XYWing`, `XYZWing`, `WXYZWingBasic` +3. `Turbot2StringKite` und `TurbotSkyscraper` +4. `SimpleColoringT1` +5. `EmptyRectangle` +6. `UniqueRectangleT1`, `UniqueRectangleT4`, `UniqueRectangleT7` +7. `XChain`, `XYChain`, `XChainLoop`, `XYChainLoop` +8. `CRP`, nachdem die genaue fachliche Bedeutung und Akzeptanzkriterien + dokumentiert wurden + +Für jede Technik wird zuerst ein isoliertes Testmuster festgelegt. Ein leerer +Typ ohne Verhalten gilt nicht als implementierte Strategie. + +## Phase 7 – Vollständige algorithmische Solver (P2) + +- Backtracking-Solver mit Minimum-Remaining-Values-Heuristik implementieren. +- optional einen DLX-/Algorithm-X-Solver ergänzen. +- Eindeutigkeit einer Lösung prüfen und die Fälle keine, genau eine oder mehrere + Lösungen unterscheiden. +- algorithmische Solver als Referenz in Tests verwenden, um Ergebnisse des + menschlichen Solvers zu validieren. +- explizit konfigurieren, ob ein algorithmischer Solver nur prüft, als Fallback + dient oder direkt löst. + +Abgeschlossen, wenn alle gültigen klassischen 9x9-Rätsel entweder gelöst oder +eindeutig als unlösbar/mehrdeutig klassifiziert werden. + +## Phase 8 – Kommandozeile und Bedienbarkeit (P2) + +- Flags für Datei, Puzzle-Index, direkte Zeichenfolge und Standard-Eingabe + hinzufügen. +- Solverart und zugelassene Strategien auswählbar machen. +- Ausgabeoptionen für Ausgangsfeld, Endfeld, Einzelschritte und JSON anbieten. +- konsistente Exit-Codes für Eingabefehler, ungültige Rätsel, Stillstand und + erfolgreiche Lösung definieren. +- Bibliothekspakete frei von direkter Konsolenausgabe halten; strukturiertes, + optionales Logging nur an den Anwendungsgrenzen einführen. +- große Puzzle-Bank-Dateien streamen, wenn nur ein Datensatz benötigt wird. + +Abgeschlossen, wenn das Programm ohne Quellcodeänderung mit eigenen Rätseln +verwendet werden kann. + +## Phase 9 – Qualität, Performance und Release (P2/P3) + +- Fuzz-Tests für Parser, Koordinatenzugriffe und Änderungsanwendung ergänzen. +- Integrationssuite über repräsentative einfache, mittlere, schwere, ungültige + und mehrdeutige Rätsel aufbauen. +- `go test -race ./...` in den Standardprüfungen aufnehmen. +- Benchmarks für Kandidatenberechnung, Strategie-Suche und vollständige Solver + hinzufügen; erst danach gezielt optimieren. +- CI für Formatierung, Tests, Vet und Race Detector einrichten. +- öffentliche APIs mit GoDoc dokumentieren und Beispiele ergänzen. +- README nach Stabilisierung von den Warnungen befreien, Versionsschema und + Changelog festlegen und ein erstes Release markieren. + +## Empfohlene nächste Arbeitspakete + +Diese Tickets bilden die kürzeste Route zu einem stabilen Zwischenstand: + +1. Test-Helfer und Feldzugriffs-Tests erstellen. +2. `ForEachCell`, `GetCell` und `Field.String` korrigieren. +3. Change-Aktionen sowie Nil- und Werteprüfung absichern. +4. `LastDigit` deduplizieren und den bekannten Panic per Regressionstest + beseitigen. +5. `HiddenSingle` korrigieren und vollständig testen. +6. `Part.IsSolved`, `Field.IsValid` und `Field.IsSolved` implementieren. +7. Puzzle-Bank-Parser atomar und indexsicher machen. +8. Solver-Schrittergebnis und Konflikterkennung einführen. +9. die vier Basisstrategien durch End-to-End-Rätseltests absichern. +10. erst danach Paar-/Tripel-Strategien oder neue Bedienfunktionen beginnen. + +Nach jedem Arbeitspaket müssen `gofmt`, `go test ./...` und `go vet ./...` +erfolgreich sein. Neue bekannte Baseline-Fehler sollen nicht angesammelt werden.