Last active
August 24, 2021 12:15
-
-
Save nkcmr/d0427bc4e5e6a4dbd12ea4077112a06b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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