Skip to content

Commit

Permalink
chore: added generic input for combinations (#12)
Browse files Browse the repository at this point in the history
Co-authored-by: Max Schmitt <max@schmitt.mx>
  • Loading branch information
ilian2233 and mxschmitt committed Oct 28, 2022
1 parent 5c498f6 commit 3a0377e
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 4 deletions.
8 changes: 4 additions & 4 deletions combinations.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import "math/bits"

// All returns all combinations for a given string array.
// This is essentially a powerset of the given set except that the empty set is disregarded.
func All(set []string) (subsets [][]string) {
func All[T any](set []T) (subsets [][]T) {
length := uint(len(set))

// Go through all possible combinations of objects
// from 1 (only first object in subset) to 2^length (all objects in subset)
for subsetBits := 1; subsetBits < (1 << length); subsetBits++ {
var subset []string
var subset []T

for object := uint(0); object < length; object++ {
// checks if object is contained in subset
Expand All @@ -29,7 +29,7 @@ func All(set []string) (subsets [][]string) {

// Combinations returns combinations of n elements for a given string array.
// For n < 1, it equals to All and returns all combinations.
func Combinations(set []string, n int) (subsets [][]string) {
func Combinations[T any](set []T, n int) (subsets [][]T) {
length := uint(len(set))

if n > len(set) {
Expand All @@ -43,7 +43,7 @@ func Combinations(set []string, n int) (subsets [][]string) {
continue
}

var subset []string
var subset []T

for object := uint(0); object < length; object++ {
// checks if object is contained in subset
Expand Down
72 changes: 72 additions & 0 deletions combinations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,78 @@ func TestStringCombinations(t *testing.T) {
}
}

func TestIntegerCombinations(t *testing.T) {
tt := []struct {
name string
in []int
out [][]int
}{
{
name: "Empty slice",
in: []int{},
out: nil,
},
{
name: "Single item",
in: []int{1},
out: [][]int{
{1},
},
},
{
name: "Two items",
in: []int{1, 2},
out: [][]int{
{1},
{2},
{1, 2},
},
},
{
name: "Three items",
in: []int{1, 2, 3},
out: [][]int{
{1},
{2},
{1, 2},
{3},
{1, 3},
{2, 3},
{1, 2, 3},
},
},
{
name: "Four items",
in: []int{1, 2, 3, 4},
out: [][]int{
{1},
{2},
{1, 2},
{3},
{1, 3},
{2, 3},
{1, 2, 3},
{4},
{1, 4},
{2, 4},
{1, 2, 4},
{3, 4},
{1, 3, 4},
{2, 3, 4},
{1, 2, 3, 4},
},
},
}
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
out := All(tc.in)
if !reflect.DeepEqual(out, tc.out) {
t.Errorf("error: \nreturn:\t%v\nwant:\t%v", out, tc.out)
}
})
}
}

func ExampleAll() {
combinations := All([]string{"A", "B", "C"})
fmt.Println(combinations)
Expand Down

0 comments on commit 3a0377e

Please sign in to comment.