- Add maxAttempts (100) to prevent infinite loops in GenerateRandomTomography - Scale timeout with grid size (max(w,h) seconds) - Simplify redundant branch in generateLinePossibilitiesRecursive - Add 15x15 and 20x20 uniqueness tests with skip conditions
- commit
- a61c52e9d9bc914ca1c941bb5bda081bca2a07d1
- parent
- 5397c4ced5f9782310ddc142ace1c4a229f207aa
- author
- Dami <dami.etoile@gmail.com>
| M | nonogram/ | 13 | ++++++---- |
| M | nonogram/ | 38 | ++++++++++++++++++++++++++++++ |
@@ -7,9 +7,13 @@ import (
77 "time"88 )99 10+const maxAttempts = 10011+1012 func GenerateRandomTomography(mode NonogramMode) Hints {11- timeout := 5 * time.Second12- for {13+ maxDim := max(mode.Width, mode.Height)14+ timeout := time.Duration(maxDim) * time.Second15+16+ for range maxAttempts {1317 s := generateRandomState(mode.Height, mode.Width, mode.Density)1418 g := newGrid(s)1519 hints := generateTomography(g)@@ -23,6 +27,7 @@ func GenerateRandomTomography(mode NonogramMode) Hints {
2327 return hints2428 }2529 }30+ return Hints{}2631 }2732 2833 func generateRandomState(h, w int, density float64) state {@@ -317,10 +322,8 @@ func generateLinePossibilitiesRecursive(length int, hint []int, hintIdx, pos int
317322 318323 if hintIdx < len(hint)-1 {319324 newCurrent = append(newCurrent, cellEmpty)320- results = append(results, generateLinePossibilitiesRecursive(length, hint, hintIdx+1, len(newCurrent), newCurrent)...)321- } else {322- results = append(results, generateLinePossibilitiesRecursive(length, hint, hintIdx+1, len(newCurrent), newCurrent)...)323325 }326+ results = append(results, generateLinePossibilitiesRecursive(length, hint, hintIdx+1, len(newCurrent), newCurrent)...)324327 }325328 326329 return results@@ -867,6 +867,44 @@ func TestGenerateRandomTomography_10x10_Unique(t *testing.T) {
867867 }868868 }869869 870+func TestGenerateRandomTomography_15x15_Unique(t *testing.T) {871+ mode := NewMode("Test 15x15", "test mode", 15, 15, 0.5)872+873+ hints := GenerateRandomTomography(mode)874+ if len(hints.rows) == 0 && len(hints.cols) == 0 {875+ t.Skip("15x15 generation timed out or exhausted attempts")876+ }877+878+ ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)879+ defer cancel()880+881+ count := countSolutions(hints, mode.Width, mode.Height, 2, ctx)882+ if count != 1 {883+ t.Errorf("puzzle has %d solutions, want 1", count)884+ }885+}886+887+func TestGenerateRandomTomography_20x20_Unique(t *testing.T) {888+ if testing.Short() {889+ t.Skip("skipping 20x20 in short mode")890+ }891+892+ mode := NewMode("Test 20x20", "test mode", 20, 20, 0.5)893+894+ hints := GenerateRandomTomography(mode)895+ if len(hints.rows) == 0 && len(hints.cols) == 0 {896+ t.Skip("20x20 generation timed out or exhausted attempts")897+ }898+899+ ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)900+ defer cancel()901+902+ count := countSolutions(hints, mode.Width, mode.Height, 2, ctx)903+ if count != 1 {904+ t.Errorf("puzzle has %d solutions, want 1", count)905+ }906+}907+870908 // Ensure the game import is used (it's needed for the init() registration side effect871909 // and the NewMode constructor uses game.NewBaseMode internally).872910 var _ game.Gamer = Model{}