From 647b79a0506a773076811bc024a170c3a108898b Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 17 Dec 2025 18:29:19 -0500 Subject: [PATCH] feat: valid sudoku --- pkg/valid_sudoku/main.go | 46 ++++++++++++++++++++++++++++ pkg/valid_sudoku/main_test.go | 56 +++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 pkg/valid_sudoku/main.go create mode 100644 pkg/valid_sudoku/main_test.go diff --git a/pkg/valid_sudoku/main.go b/pkg/valid_sudoku/main.go new file mode 100644 index 0000000..9a75d0e --- /dev/null +++ b/pkg/valid_sudoku/main.go @@ -0,0 +1,46 @@ +package valid_sudoku + +type Multiset map[byte]bool + +func (m Multiset) Add(b byte) bool { + if b == '.' { + return true + } + + exists := m[b] + m[b] = true + return !exists +} + +func IsValidSudoku(board [][]byte) bool { + for i := range 3 { + for j := range 3 { + box := Multiset{} + + for x := range 3 { + for y := range 3 { + if !box.Add(board[3*j+y][3*i+x]) { + return false + } + } + } + } + } + + for i := range 9 { + row := Multiset{} + column := Multiset{} + + for j := range 9 { + if !row.Add(board[i][j]) { + return false + } + + if !column.Add(board[j][i]) { + return false + } + } + } + + return true +} diff --git a/pkg/valid_sudoku/main_test.go b/pkg/valid_sudoku/main_test.go new file mode 100644 index 0000000..4192ae9 --- /dev/null +++ b/pkg/valid_sudoku/main_test.go @@ -0,0 +1,56 @@ +package valid_sudoku_test + +import ( + "testing" + + "git.maximhutz.com/practice/pkg/valid_sudoku" + "github.com/stretchr/testify/assert" +) + +func Test1(t *testing.T) { + board := [][]byte{ + {'5', '3', '.', '.', '7', '.', '.', '.', '.'}, + {'6', '.', '.', '1', '9', '5', '.', '.', '.'}, + {'.', '9', '8', '.', '.', '.', '.', '6', '.'}, + {'8', '.', '.', '.', '6', '.', '.', '.', '3'}, + {'4', '.', '.', '8', '.', '3', '.', '.', '1'}, + {'7', '.', '.', '.', '2', '.', '.', '.', '6'}, + {'.', '6', '.', '.', '.', '.', '2', '8', '.'}, + {'.', '.', '.', '4', '1', '9', '.', '.', '5'}, + {'.', '.', '.', '.', '8', '.', '.', '7', '9'}, + } + + assert.True(t, valid_sudoku.IsValidSudoku(board)) +} + +func Test2(t *testing.T) { + board := [][]byte{ + {'8', '3', '.', '.', '7', '.', '.', '.', '.'}, + {'6', '.', '.', '1', '9', '5', '.', '.', '.'}, + {'.', '9', '8', '.', '.', '.', '.', '6', '.'}, + {'8', '.', '.', '.', '6', '.', '.', '.', '3'}, + {'4', '.', '.', '8', '.', '3', '.', '.', '1'}, + {'7', '.', '.', '.', '2', '.', '.', '.', '6'}, + {'.', '6', '.', '.', '.', '.', '2', '8', '.'}, + {'.', '.', '.', '4', '1', '9', '.', '.', '5'}, + {'.', '.', '.', '.', '8', '.', '.', '7', '9'}, + } + + assert.False(t, valid_sudoku.IsValidSudoku(board)) +} + +func Test3(t *testing.T) { + board := [][]byte{ + {'.', '.', '.', '.', '5', '.', '.', '1', '.'}, + {'.', '4', '.', '3', '.', '.', '.', '.', '.'}, + {'.', '.', '.', '.', '.', '3', '.', '.', '1'}, + {'8', '.', '.', '.', '.', '.', '.', '2', '.'}, + {'.', '.', '2', '.', '7', '.', '.', '.', '.'}, + {'.', '1', '5', '.', '.', '.', '.', '.', '.'}, + {'.', '.', '.', '.', '.', '2', '.', '.', '.'}, + {'.', '2', '.', '9', '.', '.', '.', '.', '.'}, + {'.', '.', '4', '.', '.', '.', '.', '.', '.'}, + } + + assert.False(t, valid_sudoku.IsValidSudoku(board)) +}