Compare commits

...

24 Commits

Author SHA1 Message Date
c47e2e4cb2 feat: monday 2026-02-02 18:23:19 -05:00
5f33c164d9 feat: osvijrsi 2026-01-26 19:24:25 -05:00
63e7b31184 feat:s oivjsovji 2026-01-23 23:11:32 -05:00
a2492aad21 feat: thrusday 2026-01-22 17:48:18 -05:00
364fd261e9 feat: wednesday 2026-01-21 17:45:55 -05:00
afa3b30e98 ss 2026-01-20 19:49:23 -05:00
15160f6451 feaf 2026-01-20 19:49:06 -05:00
80c4ee3bf2 feat: monday 2026-01-19 18:42:26 -05:00
e53fbf0ec6 feat: sunday 2026-01-18 14:15:59 -05:00
0c5444e63a feat: saturday 2026-01-17 13:39:20 -05:00
1d47afa321 feat: friday 2026-01-16 18:23:43 -05:00
b629395a1a feat: tuesday 2026-01-13 18:01:52 -05:00
5fb803129f feat: monday 2026-01-12 19:38:01 -05:00
f3abe4ff5b feat: sunday 2026-01-11 15:42:42 -05:00
32173210d6 feat: three sum 2026-01-10 19:52:57 -05:00
Max
c3f6b6758f feat: palindrome 2026-01-08 18:04:43 -05:00
Max
3722df466f feat: largest rectangle 2026-01-07 19:56:22 -05:00
Max
20629eab22 feat: longest consecutive sequence 2026-01-07 18:54:55 -05:00
Max
2fc909f9c7 feat: works 2025-12-24 13:59:58 -05:00
Max
6db53a1fb9 feat: progress 2025-12-23 23:55:44 -05:00
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
32 changed files with 1290 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
package besttimetobuyandsellstock
func MaxProfit(prices []int) int {
buy, sell := 1_000_000_000, 0
for _, price := range prices {
buy, sell = min(buy, price), max(sell, price-buy)
}
return sell
}

105
pkg/car_fleet/main.go Normal file
View File

@@ -0,0 +1,105 @@
package car_fleet
import (
"math"
"slices"
)
type Car struct {
Position float64
Speed float64
}
// The TIME at which the two cars will collide with each other.
func (c Car) CollidesInto(o Car) float64 {
if c.Speed == o.Speed {
return math.Inf(1)
}
return float64(c.Position-o.Position) / float64(o.Speed-c.Speed)
}
// The DISTANCE the car will be at a point in time.
func (c Car) At(time float64) float64 {
return c.Position + c.Speed*time
}
// The TIME the car will reach a certain distance.
func (c Car) Reaches(target float64) float64 {
if c.Speed == 0 {
return math.Inf(1)
}
return (target - c.Position) / c.Speed
}
type Interval struct {
From float64
To float64
}
func (i Interval) Contains(point float64) bool {
return point >= i.From && point <= i.To
}
func (i Interval) Intersect(o Interval) Interval {
return Interval{
From: max(i.From, o.From),
To: min(i.To, o.To),
}
}
type Trajectory struct {
Car
Interval
}
func sortByInversePosition(a Car, b Car) int {
return int(b.Position - a.Position)
}
func CarFleet(target int, position []int, speed []int) int {
cars := []Car{}
ends := map[float64]bool{}
for i := range position {
cars = append(cars, Car{
Position: float64(position[i]),
Speed: float64(speed[i]),
})
}
slices.SortFunc(cars, sortByInversePosition)
stack := []Trajectory{}
for _, car := range cars {
fastest_trajectory := Trajectory{
Car: car,
Interval: Interval{
From: 0,
To: car.Reaches(float64(target)),
},
}
for {
if len(stack) == 0 {
stack = append(stack, fastest_trajectory)
break
}
first_trajectory := stack[len(stack)-1]
collision_time := car.CollidesInto(first_trajectory.Car)
if fastest_trajectory.Intersect(first_trajectory.Interval).Contains(collision_time) {
first_trajectory.From = collision_time
fastest_trajectory.To = collision_time
stack = append(stack, fastest_trajectory)
break
}
stack = stack[:len(stack)-1]
}
ends[stack[0].To] = true
}
return len(ends)
}

View File

@@ -0,0 +1,44 @@
package car_fleet_test
import (
"testing"
"git.maximhutz.com/practice/pkg/car_fleet"
"github.com/stretchr/testify/assert"
)
func Test1(t *testing.T) {
target := 12
position := []int{10, 8, 0, 5, 3}
speed := []int{2, 4, 1, 1, 3}
output := 3
assert.Equal(t, output, car_fleet.CarFleet(target, position, speed))
}
func Test2(t *testing.T) {
target := 10
position := []int{3}
speed := []int{3}
output := 1
assert.Equal(t, output, car_fleet.CarFleet(target, position, speed))
}
func Test3(t *testing.T) {
target := 100
position := []int{0, 2, 4}
speed := []int{4, 2, 1}
output := 1
assert.Equal(t, output, car_fleet.CarFleet(target, position, speed))
}
func Test4(t *testing.T) {
target := 10
position := []int{6, 8}
speed := []int{3, 2}
output := 2
assert.Equal(t, output, car_fleet.CarFleet(target, position, speed))
}

View File

@@ -0,0 +1,65 @@
package constructbinarytreefrompreorderandinordertraversal
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
type NodeInfo struct {
Val int
Preorder int
Inorder int
}
func buildTreeInfo(info []NodeInfo) *TreeNode {
if len(info) == 0 {
return nil
}
root_info := info[0]
for _, datum := range info {
if datum.Preorder < root_info.Preorder {
root_info = datum
}
}
left_info := []NodeInfo{}
right_info := []NodeInfo{}
for _, datum := range info {
if datum.Inorder < root_info.Inorder {
left_info = append(left_info, datum)
} else if datum.Inorder > root_info.Inorder {
right_info = append(right_info, datum)
} else {
continue
}
}
return &TreeNode{
Val: root_info.Val,
Left: buildTreeInfo(left_info),
Right: buildTreeInfo(right_info),
}
}
func buildTree(preorder []int, inorder []int) *TreeNode {
info_map := map[int]*NodeInfo{}
for o, v := range preorder {
info_map[v] = &NodeInfo{
Val: v,
Preorder: o,
}
}
for o, v := range inorder {
info_map[v].Inorder = o
}
info := []NodeInfo{}
for _, datum := range info_map {
info = append(info, *datum)
}
return buildTreeInfo(info)
}

View File

@@ -0,0 +1,36 @@
package container_with_most_water
func MaxArea(height []int) int {
if len(height) < 2 {
return 0
}
start := 0
end := len(height) - 1
// Let:
// - A = the smaller side,
// - B = the larger side.
//
// Notice that:
// - Any container with A cannot have a height larger than `min(A, B)`.
// - Any container with A cannot have a width larger than `B - A`.
//
// Because of this, all solutions containing A cannot be larger than `area`.
area := (end - start) * min(height[start], height[end])
// Futhermore, we can completely ignore A.
//
// The maximum area will either be the current `area`, or some other two
// lines in the subset without A.
var subset []int
if height[start] < height[end] {
subset = height[start+1:]
} else {
subset = height[:end]
}
// We can now evaluate the problem space in the subset, and compute the
// maximum area.
return max(area, MaxArea(subset))
}

View File

@@ -0,0 +1,13 @@
package findminimuminrotatedsortedarray
func FindMin(nums []int) int {
middle := len(nums) / 2
if nums[0] > nums[middle] {
return FindMin(nums[1 : middle+1])
} else if nums[middle] > nums[len(nums)-1] {
return FindMin(nums[middle+1:])
} else {
return nums[0]
}
}

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,60 @@
package largest_rectangle_in_histogram
type Box struct {
Start int
Height int
}
// Calculates the size of the box, from its starting point upto (and NOT
// including) a certain point.
func (b Box) Size(upto int) int {
return (upto - b.Start) * b.Height
}
func LargestRectangleArea(heights []int) int {
// This is a stack, containing all boxes that haven't been completed yet. Each
// box contains two integers. The first is the starting index, and the second
// is the height of the box.
boxes := []Box{}
// The accumulation of the biggest box so far.
biggest := 0
// Add a number that is guaranted to be lower than any other. This will pop out
// any boxes left in the stack at the end of the program.
heights = append(heights, -1)
for i, height := range heights {
// This is the farthest index back where the eventual new box can start.
// Everytime we pop a box off the top of the stack, this means every item
// from the start of the box until now is > the current height. So, we can
// extend that box at least that far back.
farthest := i
for len(boxes) > 0 {
top := boxes[len(boxes)-1]
// The boxes are implicitly ordered by height. When one gets the top box,
// all below must have a <= height.
//
// If the very top box has a height <= to the current height, that means
// all boxes left will carry over into the next iteration, so we can continue.
if top.Height < height {
break
}
// Since this box is taller than the current height, it ends here.
// We calculate its size, and accumulate it in the `biggest` variable.
biggest = max(biggest, top.Size(i))
// Remove it from the stack.
boxes = boxes[:len(boxes)-1]
// Push the starting point of the box farther back.
farthest = top.Start
}
// A box is always created for each new height.
boxes = append(boxes, Box{Start: farthest, Height: height})
}
return biggest
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,28 @@
package linked_list_cycle
type ListNode struct {
Val int
Next *ListNode
}
func succeed(n *ListNode) *ListNode {
if n == nil {
return n
} else {
return n.Next
}
}
func HasCycle(head *ListNode) bool {
one, two := head, succeed(head)
for one != nil && two != nil {
if one == two {
return true
}
one, two = succeed(one), succeed(succeed(two))
}
return false
}

View File

@@ -0,0 +1,86 @@
package longest_consecutive_sequence
// type Node struct {
// // The location of the parent node.
// Parent *Node
// // The number of descendent nodes, including itself.
// Children int
// }
// func FindAncestor(n *Node) *Node {
// ancestor := n
// for ancestor.Parent != nil {
// ancestor = ancestor.Parent
// }
// return ancestor
// }
// func LongestConsecutive(nums []int) int {
// nodes := map[int]*Node{}
// for _, num := range nums {
// if _, exists := nodes[num]; exists {
// continue
// }
// node := &Node{Parent: nil, Children: 1}
// if lower, lower_exists := nodes[num-1]; lower_exists {
// ancestor := FindAncestor(lower)
// ancestor.Parent = node
// node.Children += ancestor.Children
// }
// if upper, lower_exists := nodes[num+1]; lower_exists {
// ancestor := FindAncestor(upper)
// ancestor.Parent = node
// node.Children += ancestor.Children
// }
// nodes[num] = node
// }
// maximum := 0
// for _, node := range nodes {
// maximum = max(maximum, node.Children)
// }
// return maximum
// }
func LongestConsecutive(nums []int) int {
items := map[int]bool{}
for _, num := range nums {
items[num] = true
}
maximum := 0
for item, unused := range items {
if !unused {
continue
}
items[item] = false
sequence := 1
for i := item - 1; items[i]; i-- {
items[i] = false
sequence++
}
for i := item + 1; items[i]; i++ {
items[i] = false
sequence++
}
maximum = max(maximum, sequence)
}
return maximum
}

View File

@@ -0,0 +1,32 @@
package longest_consecutive_sequence_test
import (
"testing"
"git.maximhutz.com/practice/pkg/longest_consecutive_sequence"
"github.com/stretchr/testify/assert"
)
func Test1(t *testing.T) {
assert.Equal(t, 4, longest_consecutive_sequence.LongestConsecutive([]int{100, 4, 200, 1, 3, 2}))
}
func Test2(t *testing.T) {
assert.Equal(t, 9, longest_consecutive_sequence.LongestConsecutive([]int{0, 3, 7, 2, 5, 8, 4, 6, 0, 1}))
}
func Test3(t *testing.T) {
assert.Equal(t, 3, longest_consecutive_sequence.LongestConsecutive([]int{1, 0, 1, 2}))
}
func Test4(t *testing.T) {
assert.Equal(t, 0, longest_consecutive_sequence.LongestConsecutive([]int{}))
}
func Test5(t *testing.T) {
assert.Equal(t, 7, longest_consecutive_sequence.LongestConsecutive([]int{1, 3, 5, 7, 2, 6, 4}))
}
func Test6(t *testing.T) {
assert.Equal(t, 7, longest_consecutive_sequence.LongestConsecutive([]int{1, 3, 5, 7, 2, 6, 4}))
}

View File

@@ -0,0 +1,63 @@
package mergeksortedlists
import "container/heap"
type ListNode struct {
Val int
Next *ListNode
}
type ListNodeHeap []*ListNode
func (l ListNodeHeap) Len() int {
return len(l)
}
func (l ListNodeHeap) Less(i int, j int) bool {
if l[i] == nil {
return true
}
if l[j] == nil {
return false
}
return l[i].Val < l[j].Val
}
func (l *ListNodeHeap) Pop() (popped any) {
*l, popped = (*l)[:len(*l)-1], (*l)[len(*l)-1]
return
}
func (l *ListNodeHeap) Push(x any) {
*l = append(*l, x.(*ListNode))
}
func (l ListNodeHeap) Swap(i int, j int) {
l[i], l[j] = l[j], l[i]
}
func MergeKLists(lists []*ListNode) *ListNode {
hp := ListNodeHeap(lists)
heap.Init(&hp)
sorted := ListNode{}
head := &sorted
for len(hp) > 0 {
min := heap.Pop(&hp).(*ListNode)
if min == nil {
continue
}
rest := min.Next
head.Next, head = min, min
if rest != nil {
heap.Push(&hp, rest)
}
}
return sorted.Next
}

View File

@@ -0,0 +1,33 @@
package merge_two_sorted_lists
type ListNode struct {
Val int
Next *ListNode
}
func MergeTwoLists(a *ListNode, b *ListNode) *ListNode {
result := &ListNode{}
head := result
for {
if a == nil {
if b == nil {
break
} else {
head.Next, head, b = b, b, b.Next
}
} else {
if b == nil {
head.Next, head, a = a, a, a.Next
} else {
if a.Val < b.Val {
head.Next, head, a = a, a, a.Next
} else {
head.Next, head, b = b, b, b.Next
}
}
}
}
return result.Next
}

View File

@@ -0,0 +1,95 @@
package minimumwindowsubstring
import "fmt"
type Set[T comparable] map[T]int
type Substring struct {
Main string
Left int
Right int
Set Set[byte]
}
func Better(a, b string) string {
if len(a) == 0 {
return b
} else if len(b) < len(a) {
return b
}
return a
}
func NewSubstring(s string) Substring {
return Substring{s, 0, len(s) - 1, NewSet(s)}
}
func (s Set[T]) SubsetOf(t Set[T]) bool {
for k := range s {
if s[k] > t[k] {
return false
}
}
return true
}
func NewSet(t string) Set[byte] {
set := Set[byte]{}
for i := range t {
set[t[i]]++
}
return set
}
func (s *Substring) CullLeft(t Substring) {
for s.Set[s.Main[s.Left]] > t.Set[s.Main[s.Left]] {
s.Set[s.Main[s.Left]]--
s.Left++
}
fmt.Println("CANNOT CULL", string(s.Main[s.Left]))
}
func (s *Substring) IncRight() bool {
if s.Right == len(s.Main)-1 {
return false
}
s.Right++
s.Set[s.Main[s.Right]]++
return true
}
func (s Substring) String() string {
return s.Main[s.Left : s.Right+1]
}
func (s *Substring) CullRight(t Substring) {
for s.Set[s.Main[s.Right]] > t.Set[s.Main[s.Right]] {
s.Set[s.Main[s.Right]]--
s.Right--
}
}
func minWindow(s string, t string) string {
ss, tt := NewSubstring(s), NewSubstring(t)
best_answer := ""
if !tt.Set.SubsetOf(ss.Set) {
return best_answer
}
ss.CullRight(tt)
ss.CullLeft(tt)
best_answer = Better(best_answer, ss.String())
for ss.IncRight() {
ss.CullLeft(tt)
best_answer = Better(best_answer, ss.String())
}
return best_answer
}

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,27 @@
package removenthnodefromendoflist
type ListNode struct {
Val int
Next *ListNode
}
func RemoveNthFromEnd(head *ListNode, n int) *ListNode {
nodes := []*ListNode{}
for head != nil {
nodes = append(nodes, head)
head = head.Next
}
if n == len(nodes) {
return nodes[0].Next
}
if n == 1 {
nodes[len(nodes)-2].Next = nil
return nodes[0]
}
nodes[len(nodes)-(n+1)].Next = nodes[len(nodes)-(n-1)]
return nodes[0]
}

34
pkg/reorder_list/main.go Normal file
View File

@@ -0,0 +1,34 @@
package reorderlist
type ListNode struct {
Val int
Next *ListNode
}
func ReorderList(head *ListNode) {
nodes := []*ListNode{}
for head != nil {
nodes = append(nodes, head)
head = head.Next
}
start := 0
end := len(nodes) - 1
for {
if start == end {
nodes[start].Next = nil
return
}
nodes[start].Next = nodes[end]
start++
if start == end {
nodes[end].Next = nil
return
}
nodes[end].Next = nodes[start]
end--
}
}

View File

@@ -0,0 +1,19 @@
package reverse_linked_list
type ListNode struct {
Val int
Next *ListNode
}
func ReverseList(head *ListNode) *ListNode {
var reversed *ListNode = nil
current := head
for current != nil {
next := current.Next
current.Next = reversed
reversed, current = current, next
}
return reversed
}

View File

@@ -0,0 +1,30 @@
package searchinrotatedsortedarray
func searchHelper(nums []int, target int, offset int) int {
if len(nums) == 0 {
return -1
}
middle := len(nums) / 2
if target == nums[middle] {
return middle + offset
}
if nums[0] > nums[middle] {
if target >= nums[0] || target <= nums[middle] {
return searchHelper(nums[:middle], target, offset)
} else {
return searchHelper(nums[middle+1:], target, offset+(middle+1))
}
} else {
if target >= nums[0] && target <= nums[middle] {
return searchHelper(nums[:middle], target, offset)
} else {
return searchHelper(nums[middle+1:], target, offset+(middle+1))
}
}
}
func Search(nums []int, target int) int {
return searchHelper(nums, target, 0)
}

41
pkg/three_sum/main.go Normal file
View File

@@ -0,0 +1,41 @@
package three_sum
import (
"slices"
)
func TwoSum(numbers []int, target int, solutions map[[3]int]bool) {
start := 0
end := len(numbers) - 1
for start < end {
sum := numbers[start] + numbers[end]
if sum < target {
start++
} else if sum > target {
end--
} else {
solutions[[3]int{-target, numbers[start], numbers[end]}] = true
start++
}
}
}
func ThreeSum(nums []int) [][]int {
slices.Sort(nums)
solutions := map[[3]int]bool{}
for i := range nums {
TwoSum(nums[i+1:], -nums[i], solutions)
}
result := [][]int{}
for solution := range solutions {
result = append(result, solution[:])
}
return result
}

View File

@@ -0,0 +1,26 @@
package three_sum_test
import (
"testing"
"git.maximhutz.com/practice/pkg/three_sum"
"github.com/stretchr/testify/assert"
)
func Test1(t *testing.T) {
assert.ElementsMatch(t,
[][]int{{-1, -1, 2}, {-1, 0, 1}},
three_sum.ThreeSum([]int{-1, 0, 1, 2, -1, -4}))
}
func Test2(t *testing.T) {
assert.Equal(t,
[][]int{},
three_sum.ThreeSum([]int{0, 1, 1}))
}
func Test3(t *testing.T) {
assert.Equal(t,
[][]int{{0, 0, 0}},
three_sum.ThreeSum([]int{0, 0, 0}))
}

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

View File

@@ -0,0 +1,31 @@
package trapping_rain_water
func Trap(heights []int) int {
// Calculate area taken up by the boundary.
boundary_area := 0
for _, height := range heights {
boundary_area += height
}
// Calculate the total area taken up by the boundary and the water.
total_area := 0
left := 0
left_height := 0
right := len(heights) - 1
right_height := 0
for left <= right {
left_height = max(left_height, heights[left])
right_height = max(right_height, heights[right])
if left_height < right_height {
total_area += left_height
left++
} else {
total_area += right_height
right--
}
}
return total_area - boundary_area
}

View File

@@ -0,0 +1,31 @@
package trapping_rain_water
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestTrap_Example1(t *testing.T) {
height := []int{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}
expected := 6
result := Trap(height)
assert.Equal(t, expected, result)
}
func TestTrap_Example2(t *testing.T) {
height := []int{4, 2, 0, 3, 2, 5}
expected := 9
result := Trap(height)
assert.Equal(t, expected, result)
}
func TestTrap_Example3(t *testing.T) {
height := []int{0}
expected := 0
result := Trap(height)
assert.Equal(t, expected, result)
}

View File

@@ -0,0 +1,30 @@
package valid_palindrome
import (
"regexp"
"strings"
)
var notAlphanumeric = regexp.MustCompile(`[^a-zA-Z0-9]`)
func KeepAlphanumeric(text string) string {
return notAlphanumeric.ReplaceAllString(text, "")
}
func IsPalindrome(text string) bool {
scrubbed := strings.ToLower(KeepAlphanumeric(text))
start := 0
end := len(scrubbed) - 1
for start < end {
if scrubbed[start] != scrubbed[end] {
return false
}
start++
end--
}
return true
}

View File

@@ -0,0 +1,14 @@
package valid_palindrome_test
import (
"testing"
"git.maximhutz.com/practice/pkg/valid_palindrome"
"github.com/stretchr/testify/assert"
)
func TestTwoSum(t *testing.T) {
assert.Equal(t, true, valid_palindrome.IsPalindrome("A man, a plan, a canal: Panama"))
assert.Equal(t, false, valid_palindrome.IsPalindrome("race a car"))
assert.Equal(t, true, valid_palindrome.IsPalindrome(" "))
}

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