Commit Diff


commit - 61655a2799a381feeccfd31bdcb622eb1fb24b5e
commit + 65bd8c99d072f7f61b5304f098001ecc71f82e71
blob - 6fb9ea8233f44c549ae5a951b6d5752010f560ce
blob + be6f6d2e6b56ad69876d505078027d0d98c97c80
--- permutation.go
+++ permutation.go
@@ -4,28 +4,24 @@ lists. It uses Go 1.18's new generics feature to provi
 */
 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
 			}
 		}
 	}
-	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
+}
blob - /dev/null
blob + 9aac26a1baca7f8e11b197fad7164a4216842f34 (mode 644)
--- /dev/null
+++ go.sum
@@ -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=
blob - 7bb94ec4947a0869eaae87b5718d42b8745b1bef
blob + 98e18775f57aef39edeecc191c1919f355556b79
--- permutation_test.go
+++ permutation_test.go
@@ -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)
+			}
+		})
+	}
+}