Browse Source

add PermutationsAllSizes

master
Evan Burkey 3 months ago
parent
commit
8a5e3c9462
  1. 2
      go.sum
  2. 49
      permutation.go
  3. 49
      permutation_test.go

2
go.sum

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326 h1:QfTh0HpN6hlw6D3vu8DAwC8pBIwikq0AI1evdm+FksE=
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=

49
permutation.go

@ -4,28 +4,24 @@ lists. It uses Go 1.18's new generics feature to provide a generic interface @@ -4,28 +4,24 @@ lists. It uses Go 1.18's new generics feature to provide a generic interface
*/
package permutation
// GenSlice is a generic slice of data
type GenSlice[T any] []T
/*
Permutations uses Heap's Algorithm to generate a list of all possible
permutations of the provided list. Most slices will automatically coerce
their type into a GenSlice[T] with no casting required
permutations of the provided list.
*/
func Permutations[T any](arr GenSlice[T]) []GenSlice[T] {
var helper func(GenSlice[T], int)
var res []GenSlice[T]
func Permutations[T comparable](arr []T) [][]T {
var heapsAlgo func([]T, int)
var res [][]T
helper = func(arr GenSlice[T], n int) {
heapsAlgo = func(arr []T, n int) {
if n == 1 {
var tmp GenSlice[T]
var tmp []T
for _, i := range arr {
tmp = append(tmp, i)
}
res = append(res, tmp)
} else {
for i := 0; i < n; i++ {
helper(arr, n-1)
heapsAlgo(arr, n-1)
if n%2 == 1 {
tmp := arr[i]
arr[i] = arr[n-1]
@ -38,6 +34,35 @@ func Permutations[T any](arr GenSlice[T]) []GenSlice[T] { @@ -38,6 +34,35 @@ func Permutations[T any](arr GenSlice[T]) []GenSlice[T] {
}
}
}
helper(arr, len(arr))
heapsAlgo(arr, len(arr))
return res
}
/*
PermutationsAllSizes returns all permutations of every possible combination in a slice.
This includes single item sets.
*/
func PermutationsAllSizes[T comparable](arr []T) (result [][]T) {
sets := generateSets(arr)
for _, set := range sets {
perms := Permutations(set)
for _, perm := range perms {
result = append(result, perm)
}
}
return result
}
func generateSets[T comparable](arr []T) (result [][]T) {
l := uint(len(arr))
for b := 1; b < (1 << l); b++ {
var s []T
for i := uint(0); i < l; i++ {
if (b>>i)&1 == 1 {
s = append(s, arr[i])
}
}
result = append(result, s)
}
return result
}

49
permutation_test.go

@ -1,12 +1,51 @@ @@ -1,12 +1,51 @@
package permutation
import (
"fmt"
"testing"
)
func Test(t *testing.T) {
a := []int{1, 2, 3, 4}
p := Permutations(a)
fmt.Println(p)
func TestPermutations(t *testing.T) {
testCases := []struct {
name string
seed []int
permsExpected int
}{
{
"basic",
[]int{1, 2, 3},
6,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
perms := Permutations(testCase.seed)
if len(perms) != testCase.permsExpected {
t.Errorf("len(perms) == %d, expected %d", len(perms), testCase.permsExpected)
}
})
}
}
func TestPermutationsAllSizes(t *testing.T) {
testCases := []struct {
name string
seed []int
permsExpected int
}{
{
"3 ints",
[]int{1, 2, 3},
15,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
perms := PermutationsAllSizes(testCase.seed)
if len(perms) != testCase.permsExpected {
t.Errorf("len(perms) == %d, expected %d", len(perms), testCase.permsExpected)
}
})
}
}

Loading…
Cancel
Save