diff --git a/helpers/cartesianProduct.go b/helpers/cartesianProduct.go new file mode 100644 index 0000000..6e5c038 --- /dev/null +++ b/helpers/cartesianProduct.go @@ -0,0 +1,34 @@ +package helpers + +// The following two functions were taken and/or modified from https://stackoverflow.com/a/29023392 + +func CartesianProduct(a []int, k int) <-chan []int { + c := make(chan []int) + lens := len(a) + r := make([]int, k) + + go func(c chan []int) { + defer close(c) + for ix := make([]int, k); ix[0] < lens; nextIndex(ix, lens) { + for i, j := range ix { + r[i] = a[j] + } + c <- r + } + }(c) + + return c +} + +// nextIndex sets ix to the lexicographically next value, +// such that for each i>0, 0 <= ix[i] < lens. +func nextIndex(ix []int, lens int) { + // https://stackoverflow.com/a/29023392 + for j := len(ix) - 1; j >= 0; j-- { + ix[j]++ + if j == 0 || ix[j] < lens { + return + } + ix[j] = 0 + } +} diff --git a/helpers/combinations.go b/helpers/combinations.go new file mode 100644 index 0000000..3aa385b --- /dev/null +++ b/helpers/combinations.go @@ -0,0 +1,26 @@ +package helpers + + +// The following two functions were taken from https://stackoverflow.com/a/19249957 + +func GenerateCombinations(alphabet string, length int) <-chan string { + c := make(chan string) + go func(c chan string) { + defer close(c) + addLetter(c, "", alphabet, length) + }(c) + return c +} + +func addLetter(c chan string, combo string, alphabet string, length int) { + if length <= 0 { + return + } + + var newCombo string + for _, ch := range alphabet { + newCombo = combo + string(ch) + c <- newCombo + addLetter(c, newCombo, alphabet, length-1) + } +}