diff --git a/combinations.go b/combinations.go index 240a828..2d9e34a 100644 --- a/combinations.go +++ b/combinations.go @@ -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 @@ -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) { @@ -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 diff --git a/combinations_test.go b/combinations_test.go index e4bfe60..9cae746 100644 --- a/combinations_test.go +++ b/combinations_test.go @@ -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)