diff --git a/math/combinatorics/permutation.go b/math/combinatorics/permutation.go new file mode 100644 index 0000000..22e22b2 --- /dev/null +++ b/math/combinatorics/permutation.go @@ -0,0 +1,11 @@ +package combinatorics + +import "github.com/lorenzotinfena/goji/utils/constraints" + +func InversePermutation[T constraints.Integer](permutation []T) []T { + inverse := make([]T, len(permutation)) + for i := 0; i < len(permutation); i++ { + inverse[permutation[i]-1] = T(i + 1) + } + return inverse +} diff --git a/math/combinatorics/robinsonschenstedmapping.go b/math/combinatorics/robinsonschenstedmapping.go new file mode 100644 index 0000000..8345296 --- /dev/null +++ b/math/combinatorics/robinsonschenstedmapping.go @@ -0,0 +1,49 @@ +package combinatorics + +import ( + "github.com/lorenzotinfena/goji/sort" + "github.com/lorenzotinfena/goji/utils" +) + +// Using code from: codeforces.com/blog/entry/98167 +func RobinsonSchenstedMapping(permutation []int) (p, q [][]int) { + sqrt := 1 + for sqrt*sqrt < len(permutation) { + sqrt++ + } + partialRobinsonSchenstedMapping := func(permutation []int) (p [][]int) { + youngTableaux := [][]int{} + for i := 0; i < len(permutation); i++ { + element := permutation[i] + for j := 0; j < sqrt; j++ { + if len(youngTableaux) == j { + youngTableaux = append(youngTableaux, []int{}) + } + ind := sort.UpperBound(youngTableaux[j], element, utils.Prioritize[int]()) + if ind == len(youngTableaux[j]) { + youngTableaux[j] = append(youngTableaux[j], element) + break + } + element, youngTableaux[j][ind] = youngTableaux[j][ind], element + } + } + return youngTableaux + } + + p = partialRobinsonSchenstedMapping(permutation) + q = partialRobinsonSchenstedMapping(InversePermutation(permutation)) + for i, j := 0, len(permutation)-1; i < j; i, j = i+1, j-1 { + permutation[i], permutation[j] = permutation[j], permutation[i] + } + pt := partialRobinsonSchenstedMapping(permutation) + qt := partialRobinsonSchenstedMapping(InversePermutation(permutation)) + for i := len(p); i < len(pt[0]); i++ { + p = append(p, []int{}) + q = append(q, []int{}) + for j := 0; j < len(pt) && i < len(pt[j]); j++ { + p[i] = append(p[i], pt[j][i]) + q[i] = append(q[i], qt[j][i]) + } + } + return +} diff --git a/math/combinatorics/robinsonschenstedmapping_test.go b/math/combinatorics/robinsonschenstedmapping_test.go new file mode 100644 index 0000000..7c6a50c --- /dev/null +++ b/math/combinatorics/robinsonschenstedmapping_test.go @@ -0,0 +1,18 @@ +package combinatorics_test + +import ( + "testing" + + "github.com/lorenzotinfena/goji/math/combinatorics" + "github.com/stretchr/testify/assert" +) + +func TestRobinsonSchenstedMapping(t *testing.T) { + p, q := combinatorics.RobinsonSchenstedMapping([]int{3, 2, 5, 4, 6, 1}) + assert.Equal(t, p, [][]int{{1, 4, 6}, {2, 5}, {3}}) + assert.Equal(t, q, [][]int{{1, 3, 5}, {2, 4}, {6}}) + + p, q = combinatorics.RobinsonSchenstedMapping([]int{3, 2, 1}) + assert.Equal(t, p, [][]int{{1}, {2}, {3}}) + assert.Equal(t, q, [][]int{{1}, {2}, {3}}) +}