C
C
chaostoken2021-01-09 16:36:02
go
chaostoken, 2021-01-09 16:36:02

How to iterate over all characters from 1 to a given length?

I need all combinations of letters and combinations. for example, there is a sequence "abc" and the maximum number of characters is 4. I want
a
b
c
aa
ab ab ba bb bv ....
vvva vvvb vvvv I.e. like

func validCombinations(alphabet string, maxChar int) bool {
    
}

// передаем возможные символы и максимальную длину
validCombinations("абв", 4)


and the function passes through all combinations

I was looking for an example. even in other languages. but all permutations, combinations, for some reason they are implemented with a given length, but I want different lengths - from 1 character to the maximum number.
Maybe there are implementations in other languages. I could adapt to go.

I understand that there are two options - recursion or a loop. I would really like to implement in a loop without recursion.

PS performance is important . while there is such a terrible implementation that he himself composed. it turns out I do something like my own number system and translate numbers into symbols
func checkCombinations(alphabet string, length int)  {
  countChars := len(alphabet)
  elems := make([]string, countChars)
  for i, r := range alphabet {
    elems[i] = string(r)
  }
  var current int
  base := float64(countChars)
  baseLog := math.Log(float64(countChars))
  for float64(current) < math.Pow(base, float64(length)) {
    if current < countChars {
      println(elems[current])
    } else {
      var combo string
      x := float64(current)
      size := int(math.Log(float64(current)) / baseLog)
      for size >= 0 {
        oneReg := math.Pow(base, float64(size))
        number := int(x / oneReg)
        x = x - oneReg*float64(number)
        combo = combo + elems[number]
        size--
      }
      println(combo)
    }
    current++
  }
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
U
uvelichitel, 2021-01-09
@uvelichitel

Well, for example, this is how you can https://play.golang.org/p/0Jnt-ONC7XO
A bit of dynamic programming) We will reuse the results of the calculations already made

func validCombinations(alphabet string, maxChar int) []string {
  var result []string = []string{""}
  var last, next int
  for i := 1; i <= maxChar; i++ {
    last = len(result)
    for _, str := range result[next:] {
      for _, char := range alphabet {
        result = append(result, str+string(char))
      }
    }
    next = last
  }
  return result
}

L
Lynn "Coffee Man", 2021-01-11
@Lynn

In order not to calculate all combinations at once, let's play with font channels:

func main() {
  ch := GenerateAllPerms("абв", 4)
  i := 1
  for s := range ch {
    fmt.Println(i, s)
    i++
  }
}

// GeneratePermsN выдаёт в канал все комбинации длины n
func GeneratePermsN(ch chan string, chars []string, prefix string, n int) {
  for _, char := range chars {
    str := prefix + char
    if n == 1 {
      ch <- str
    } else {
      GeneratePermsN(ch, chars, str, n-1)
    }
  }
}

// GenerateAllPerms возвращает канал в который будут записаны все комбинации длины от 1 до n
func GenerateAllPerms(alphabet string, n int) chan string {
  ch := make(chan string)
  chars := strings.Split(alphabet, "")
  go func() {
    for i := 1; i <= n; i++ {
      GeneratePermsN(ch, chars, "", i)
    }
    close(ch)
  }()
  return ch
}

PS Surely this code can be improved, because. I started learning Go on these January holidays =)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question