Compare commits

...

4 Commits

Author SHA1 Message Date
Max
647b79a050 feat: valid sudoku 2025-12-17 18:29:19 -05:00
Max
1e2700a2f2 fix: december 2025-12-16 20:22:52 -05:00
Max
7fdf6a520f feat: top k frequent 2025-12-15 22:39:37 -05:00
Max
da48abc0d1 feat: group anagrams 2025-12-15 21:35:21 -05:00
8 changed files with 307 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
package group_anagrams
import (
"hash/maphash"
"slices"
)
func SortString(s string) string {
runes := []rune(s)
slices.Sort(runes)
return string(runes)
}
func AnagramHash(letters string) uint64 {
var h maphash.Hash
h.WriteString(SortString(letters))
return h.Sum64()
}
func GroupAnagrams(items []string) [][]string {
anagrams := map[uint64][]string{}
for _, item := range items {
hash := AnagramHash(item)
similar, exists := anagrams[hash]
if exists {
anagrams[hash] = append(similar, item)
} else {
anagrams[hash] = []string{item}
}
}
result := [][]string{}
for _, group := range anagrams {
result = append(result, group)
}
return result
}

View File

@@ -0,0 +1,14 @@
package group_anagrams_test
// import (
// "testing"
// . "git.maximhutz.com/practice/pkg/group_anagrams"
// "github.com/stretchr/testify/assert"
// )
// func Test1(t *testing.T) {
// assert.Equal(t,
// [][]string{{"bat"}, {"nat", "tan"}, {"ate", "eat", "tea"}},
// GroupAnagrams([]string{"eat", "tea", "tan", "ate", "nat", "bat"}))
// }

View File

@@ -0,0 +1,25 @@
package product_of_array_except_self
func ProductExceptSelf(nums []int) []int {
result := []int{}
for range nums {
result = append(result, 1)
}
lower_sum := 1
for i := range len(nums) {
result[i] *= lower_sum
lower_sum *= nums[i]
}
upper_sum := 1
for i := range len(nums) {
result[len(nums)-1-i] *= upper_sum
upper_sum *= nums[len(nums)-1-i]
}
return result
}

View File

@@ -0,0 +1,16 @@
package product_of_array_except_self_test
import (
"testing"
"git.maximhutz.com/practice/pkg/product_of_array_except_self"
"github.com/stretchr/testify/assert"
)
func Test1(t *testing.T) {
assert.Equal(t, []int{24, 12, 8, 6}, product_of_array_except_self.ProductExceptSelf([]int{1, 2, 3, 4}))
}
func Test2(t *testing.T) {
assert.Equal(t, []int{0, 0, 9, 0, 0}, product_of_array_except_self.ProductExceptSelf([]int{-1, 1, 0, -3, 3}))
}

View File

@@ -0,0 +1,89 @@
package top_k_frequent_elements
/// O(n*log(n))
// func ToMultiset(nums []int) map[int]int {
// result := map[int]int{}
// for _, num := range nums {
// result[num]++
// }
// return result
// }
// func ToEntries(multiset map[int]int) [][2]int {
// result := [][2]int{}
// for num, amount := range multiset {
// result = append(result, [2]int{num, amount})
// }
// return result
// }
// func ByDescendingAmount(a, b [2]int) int {
// return b[1] - a[1]
// }
// func GetNumbers(entries [][2]int) []int {
// amounts := []int{}
// for _, entry := range entries {
// amounts = append(amounts, entry[0])
// }
// return amounts
// }
// func TopKFrequent(nums []int, k int) []int {
// multiset := ToMultiset(nums)
// entries := ToEntries(multiset)
// slices.SortFunc(entries, ByDescendingAmount)
// return GetNumbers(entries[0:k])
// }
/// O(n)
func ToMultiset(nums []int) map[int]int {
result := map[int]int{}
for _, num := range nums {
result[num]++
}
return result
}
func TopKFrequent(nums []int, k int) []int {
multiset := ToMultiset(nums)
// Bucket Sort.
//
// A multiset's frequency is always less then or equal to the length of the
// original list. So, you can use bucket sort to sort the items in O(n).
frequencies := make([][]int, len(nums))
for value, amount := range multiset {
if frequencies[amount-1] == nil {
frequencies[amount-1] = []int{}
}
frequencies[amount-1] = append(frequencies[amount-1], value)
}
top_frequencies := []int{}
for i := len(nums) - 1; i >= 0; i-- {
for _, num := range frequencies[i] {
top_frequencies = append(top_frequencies, num)
if len(top_frequencies) == k {
return top_frequencies
}
}
}
return top_frequencies
}

View File

@@ -0,0 +1,20 @@
package top_k_frequent_elements_test
import (
"testing"
"git.maximhutz.com/practice/pkg/top_k_frequent_elements"
"github.com/stretchr/testify/assert"
)
func Test1(t *testing.T) {
assert.Equal(t, []int{1, 2}, top_k_frequent_elements.TopKFrequent([]int{1, 1, 1, 2, 2, 3}, 2))
}
func Test2(t *testing.T) {
assert.Equal(t, []int{1}, top_k_frequent_elements.TopKFrequent([]int{1}, 1))
}
func Test3(t *testing.T) {
assert.Equal(t, []int{1, 4}, top_k_frequent_elements.TopKFrequent([]int{1, 4, 1, 4, 1, 4, 3, 1, 3, 4}, 2))
}

46
pkg/valid_sudoku/main.go Normal file
View File

@@ -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
}

View File

@@ -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))
}