Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzotinfena committed Mar 26, 2024
1 parent 7540d75 commit 8bcaf51
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Browser the repo here: https://pkg.go.dev/github.com/lorenzotinfena/goji
- Fibonacci heap
- Graham Scan
- Chan's algorithm
- Manacher's algorithm
- Hook length
## Coding guidelines
- When write generic code there are 2 approaches:
1. OOP: Constraint a type with a method
Expand Down
20 changes: 19 additions & 1 deletion math/basics.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ func Diff[T constraints.Integer | constraints.Float](a, b T) T {

// Assumption:
// - Multiplication is associative
func Pow2[B constraints.Float | constraints.Integer, P constraints.Integer](base B) B {
func Pow2[B constraints.Float | constraints.Integer](base B) B {
return base * base
}

// Assumption:
// - x >= 0
func Factorial[T constraints.Integer](x T, mod T) T {
res := T(1)
for x > 1 {
res *= x
res %= mod
x--
}
return res
}

// Assumption:
// - x and mod are coprimes
func ModularInverse[T constraints.Integer](x T, mod T) T {
return PowMod(x, mod-2, mod)
}
17 changes: 17 additions & 0 deletions math/binary_exponentation.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,20 @@ func Pow[B constraints.Float | constraints.Integer, P constraints.Integer](base
}
return res
}

// Pow to an integer using binary exponentiation
// Assumption:
// - Multiplication is associative
func PowMod[B constraints.Integer, P constraints.Integer](base B, power P, mod B) B {
res := B(1)
for power > 0 {
if power%2 == 1 {
res *= base
res %= mod
}
base *= base
base %= mod
power /= 2
}
return res
}
27 changes: 27 additions & 0 deletions math/combinatorics/hooklength.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package combinatorics

import "github.com/lorenzotinfena/goji/math"

func HookLength(partition []int, primeMod int) int {
partitionTrasnposed := []int{}
j := 0
for i := len(partition) - 1; i >= 0; i-- {
for j < partition[i] {
partitionTrasnposed = append(partitionTrasnposed, i+1)
j++
}
}

productOfHookLengths := 1
n := 0
for i := 0; i < len(partition); i++ {
n += partition[i]
for j := 0; j < partition[i]; j++ {
productOfHookLengths *= partitionTrasnposed[j] - i + partition[i] - j - 1
productOfHookLengths %= primeMod
}
}
hookLength := math.Factorial(n, primeMod) * math.ModularInverse(productOfHookLengths, primeMod)
hookLength %= primeMod
return (hookLength * hookLength) % primeMod
}
21 changes: 21 additions & 0 deletions math/combinatorics/integerpartition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package combinatorics

// Computes integer partitions, each partition is weakly increasing
func IntegerPartitions(n int) [][]int {
stack := []int{}
partitions := [][]int{}
var computePartitions func(remaining int, maxLength int)
computePartitions = func(remaining int, maxLength int) {
if remaining == 0 {
partitions = append(partitions, append([]int{}, stack...))
return
}
for i := 1; i <= maxLength && i <= remaining; i++ {
stack = append(stack, i)
computePartitions(remaining-i, i)
stack = stack[:len(stack)-1]
}
}
computePartitions(n, n)
return partitions
}
12 changes: 12 additions & 0 deletions math/combinatorics/integerpartition_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package combinatorics_test

import (
"testing"

"github.com/lorenzotinfena/goji/math/combinatorics"
"github.com/stretchr/testify/assert"
)

func TestIntegerPartition(t *testing.T) {
assert.Equal(t, combinatorics.IntegerPartitions(3), [][]int{{1, 1, 1}, {2, 1}, {3}})
}
32 changes: 32 additions & 0 deletions misc/manachers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package misc

// To get longest odd palidrome starting centered in i: v[2*i+1]
// To get longest even palidrome starting centered between i and i+1: v[2*i+2]
func ManachersAlgorithm[T comparable](v []T) []int {
supp := make([]T, len(v)*2+1)
var foo T
for i := 0; i < len(v); i++ {
supp[2*i] = foo
supp[2*i+1] = v[i]
}
res := make([]int, len(v)*2+1)
l := 1
r := 1
for i := 1; i < len(supp); i++ {
if i > r {
l = i
r = i
}
if res[l+r-i] < r-i {
res[i] = res[l+r-i]
} else {
res[i] = r - i
for i+res[i]+1 < len(supp) && i-res[i]-1 >= 0 && supp[i+res[i]+1] == supp[i-res[i]-1] {
res[i]++
}
l = i - res[i]
r = i + res[i]
}
}
return res
}
13 changes: 13 additions & 0 deletions misc/manachers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package misc_test

import (
"testing"

"github.com/lorenzotinfena/goji/misc"
)

func TestManachersAlgorithms(t *testing.T) {
misc.ManachersAlgorithm([]byte("abcbcbab"))
res := misc.ManachersAlgorithm([]byte("abba"))
t.Log(res[2*1+2])
}

0 comments on commit 8bcaf51

Please sign in to comment.