- Extract checkConstraints() in generator.go to share no-triples and equal-count logic between the generator and checkSolved(). - Simplify Model.checkSolved() to delegate to checkConstraints() and hasUniqueLines() instead of inlining the same checks. - Add comment to canPlace() noting it temporarily mutates the grid for row/column uniqueness testing. - Add length guard to rowEqual() for defensive safety.
- commit
- eb6280f0b60a754663b5f026b2e6f0ae3cd80c6f
- parent
- a4dbb523bbf45a5ec96c8948519584458b5b4a0d
- author
- Dami <dami.etoile@gmail.com>
| M | takuzu/ | 47 | ++---------------------------- |
| M | takuzu/ | 40 | ++++++++++++++++++++++++++ |
@@ -88,56 +88,15 @@ func (m Model) IsSolved() bool {
8888 }8989 9090 func (m Model) checkSolved() bool {91- size := m.size92- half := size / 293-9491 // All cells must be filled.95- for y := range size {96- for x := range size {92+ for y := range m.size {93+ for x := range m.size {9794 if m.grid[y][x] == emptyCell {9895 return false9996 }10097 }10198 }102-103- for i := range size {104- zeroRow, oneRow := 0, 0105- zeroCol, oneCol := 0, 0106- for j := range size {107- // Count in row.108- switch m.grid[i][j] {109- case zeroCell:110- zeroRow++111- case oneCell:112- oneRow++113- }114- // Count in column.115- switch m.grid[j][i] {116- case zeroCell:117- zeroCol++118- case oneCell:119- oneCol++120- }121-122- // Check no three consecutive in row.123- if j >= 2 && m.grid[i][j] == m.grid[i][j-1] && m.grid[i][j] == m.grid[i][j-2] {124- return false125- }126- // Check no three consecutive in column.127- if j >= 2 && m.grid[j][i] == m.grid[j-1][i] && m.grid[j][i] == m.grid[j-2][i] {128- return false129- }130- }131- if zeroRow != half || oneRow != half {132- return false133- }134- if zeroCol != half || oneCol != half {135- return false136- }137- }138-139- // Unique rows and columns.140- return hasUniqueLines(m.grid, size)99+ return checkConstraints(m.grid, m.size) && hasUniqueLines(m.grid, m.size)141100 }142101 143102 func (m Model) GetDebugInfo() string {@@ -35,6 +35,7 @@ func fillGrid(g grid, size int) bool {
3535 }3636 3737 // canPlace checks whether placing val at (x,y) would violate Takuzu constraints.38+// It temporarily mutates g[y][x] to test row/column uniqueness, then restores it.3839 func canPlace(g grid, size, x, y int, val rune) bool {3940 // Check no three consecutive in row.4041 if x >= 2 && g[y][x-1] == val && g[y][x-2] == val {@@ -195,6 +196,42 @@ func countSolutions(g grid, size, limit int) int {
195196 return 0196197 }197198 199+// checkConstraints verifies no-triples and equal-count rules for every row and column.200+func checkConstraints(g grid, size int) bool {201+ half := size / 2202+ for i := range size {203+ zeroRow, oneRow := 0, 0204+ zeroCol, oneCol := 0, 0205+ for j := range size {206+ switch g[i][j] {207+ case zeroCell:208+ zeroRow++209+ case oneCell:210+ oneRow++211+ }212+ switch g[j][i] {213+ case zeroCell:214+ zeroCol++215+ case oneCell:216+ oneCol++217+ }218+ if j >= 2 && g[i][j] == g[i][j-1] && g[i][j] == g[i][j-2] {219+ return false220+ }221+ if j >= 2 && g[j][i] == g[j-1][i] && g[j][i] == g[j-2][i] {222+ return false223+ }224+ }225+ if zeroRow != half || oneRow != half {226+ return false227+ }228+ if zeroCol != half || oneCol != half {229+ return false230+ }231+ }232+ return true233+}234+198235 // hasUniqueLines checks that all rows are unique and all columns are unique.199236 func hasUniqueLines(g grid, size int) bool {200237 // Check rows.@@ -217,6 +254,9 @@ func hasUniqueLines(g grid, size int) bool {
217254 }218255 219256 func rowEqual(a, b []rune) bool {257+ if len(a) != len(b) {258+ return false259+ }220260 for i := range a {221261 if a[i] != b[i] {222262 return false