Skip to content

Instantly share code, notes, and snippets.

@nkcmr
Last active August 24, 2021 12:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nkcmr/d0427bc4e5e6a4dbd12ea4077112a06b to your computer and use it in GitHub Desktop.
Save nkcmr/d0427bc4e5e6a4dbd12ea4077112a06b to your computer and use it in GitHub Desktop.
package main
import (
"errors"
)
// stringMatrix will iterate through every combination of each row of the matrix
// it is initialized with. while most of the time, there is a static number of
// rows in a particular matrix and it is trivial to just write something like
// this:
//
// for _, r1 := range []string{ /* ... */ } {
// for _, r2 := range []string{ /* ... */ } {
// fmt.Println("%s,%s", r1, r2)
// }
// }
//
// But this solution will only work if there are only ever 2 rows for a given
// matrix. stringMatrix is for when the number of rows is non-determinate.
// allowing usage like this:
//
// m := newMatrix([][]string{ /* ... */ })
// for {
// row, ok := m.next()
// if !ok {
// break
// }
// fmt.Println(strings.Join(row, ","))
// }
//
type stringMatrix struct {
parent *stringMatrix
items []string
idx int
}
func newMatrix(m [][]string) (*stringMatrix, error) {
if len(m) == 0 {
return nil, errors.New("cannot initialize empty matrix")
}
var mt *stringMatrix
for _, layer := range m {
if len(layer) == 0 {
return nil, errors.New("cannot initialize matrix with an empty row")
}
mt = &stringMatrix{
parent: mt,
items: layer,
}
}
mt.idx = -1
return mt, nil
}
func (m *stringMatrix) inc() bool {
root := m.parent == nil
nidx := m.idx + 1
if nidx >= len(m.items) {
if root || !m.parent.inc() {
return false
}
nidx = 0
}
m.idx = nidx
return true
}
func (m *stringMatrix) reset() {
m.idx = -1
l := m.parent
for l != nil {
l.idx = 0
l = l.parent
}
}
func (m *stringMatrix) current() []string {
vals := []string{}
l := m
for l != nil {
vals = append(vals, l.items[l.idx])
l = l.parent
}
return vals
}
func (m *stringMatrix) next() ([]string, bool) {
if ok := m.inc(); !ok {
return nil, false
}
return m.current(), true
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment