Go 从给定范围生成组合

Go 从给定范围生成组合,go,combinations,Go,Combinations,我正在尝试创建一个能够从给定范围生成组合的程序 我开始编辑下面生成组合的代码: package main import "fmt" func nextPassword(n int, c string) func() string { r := []rune(c) p := make([]rune, n) x := make([]int, len(p)) return func() string { p := p[:len(x)]

我正在尝试创建一个能够从给定范围生成组合的程序

我开始编辑下面生成组合的代码:

package main

import "fmt"

func nextPassword(n int, c string) func() string {
    r := []rune(c)
    p := make([]rune, n)
    x := make([]int, len(p))
    return func() string {
        p := p[:len(x)]
        for i, xi := range x {
            p[i] = r[xi]
        }
        for i := len(x) - 1; i >= 0; i-- {
            x[i]++
            if x[i] < len(r) {
                break
            }
            x[i] = 0
            if i <= 0 {
                x = x[0:0]
                break
            }
        }
        return string(p)
    }
}

func main() {
    np := nextPassword(2, "ABCDE")
    for {
        pwd := np()
        if len(pwd) == 0 {
            break
        }
        fmt.Println(pwd)
    }
}
这是我编辑的代码:

package main

import "fmt"

const (
    Min = 5
    Max = 10
)

func nextPassword(n int, c string) func() string {
    r := []rune(c)
    p := make([]rune, n)
    x := make([]int, len(p))
    return func() string {
        p := p[:len(x)]
        for i, xi := range x {
            p[i] = r[xi]
        }
        for i := len(x) - 1; i >= 0; i-- {
            x[i]++
            if x[i] < len(r) {
                break
            }
            x[i] = 0
            if i <= 0 {
                x = x[0:0]
                break
            }
        }
        return string(p)
    }
}

func main() {
    cont := 0
    np := nextPassword(2, "ABCDE")
    for {
        pwd := np()
        if len(pwd) == 0 {
            break
        }
        if cont >= Min && cont <= Max{
            fmt.Println(pwd)
        } else if cont > Max{
            break
        }
        cont += 1
    }
}
我的代码可以工作,但是如果我增加组合的长度,并且我的范围从中间开始,程序甚至会生成我不想要的组合,当然这需要很多时间。 如何解决这个问题?

我真的不喜欢nextPassword的编写方式,所以我做了一个改动。这个值不是从0开始并重复返回下一个值,而是获取一个整数并将其转换为相应的密码。例如,toPassword0、2、[]runeABCDE为AA,toPassword5、。。。是BA

从那里,你可以很容易地在你想要的范围内循环。但我还围绕它编写了一个nextPassword包装器,其行为与原始代码中的行为类似。这一个在封面下使用toPassword,并以n开头

此处为可运行版本:

代码如下:

package main

import (
    "fmt"
)

func toPassword(n, length int, alphabet []rune) string {
    base := len(alphabet)

    // This will be our output
    result := make([]rune, length)

    // Start filling from the right
    i := length - 1

    // This is essentially a conversion to base-b, where b is
    // the number of possible letters (5 in the case of "ABCDE")
    for n > 0 {
        // Filling from the right, put the right digit mod b
        result[i] = alphabet[n%base]

        // Divide the number by the base so we're ready for
        // the next digit
        n /= base

        // Move to the left
        i -= 1
    }

    // Fill anything that's left with "zeros" (first letter of
    // the alphabet)
    for i >= 0 {
        result[i] = alphabet[0]
        i -= 1
    }

    return string(result)
}

// Convenience function that just returns successive values from
// toPassword starting at start
func nextPassword(start, length int, alphabet []rune) func() string {
    n := start
    return func() string {
        result := toPassword(n, length, alphabet)
        n += 1
        return result
    }
}

func main() {
    for i := 5; i < 11; i++ {
        fmt.Println(toPassword(i, 2, []rune("ABCDE")))
    } // BA, BB, BC, BD, BE, CA

    // Now do the same thing using nextPassword
    np := nextPassword(5, 2, []rune("ABCDE"))
    for i := 0; i < 6; i++ {
        fmt.Println(np())
    } // BA, BB, BC, BD, BE, CA
}

您能否将此代码缩减到重现问题所需的最小代码,并澄清问题的具体内容?您是否修改了nextPassword函数?呃,编写该函数的人要么故意混淆它,要么迫切需要学习有用的变量名。
BA
BB
BC
BD
BE
CA
package main

import (
    "fmt"
)

func toPassword(n, length int, alphabet []rune) string {
    base := len(alphabet)

    // This will be our output
    result := make([]rune, length)

    // Start filling from the right
    i := length - 1

    // This is essentially a conversion to base-b, where b is
    // the number of possible letters (5 in the case of "ABCDE")
    for n > 0 {
        // Filling from the right, put the right digit mod b
        result[i] = alphabet[n%base]

        // Divide the number by the base so we're ready for
        // the next digit
        n /= base

        // Move to the left
        i -= 1
    }

    // Fill anything that's left with "zeros" (first letter of
    // the alphabet)
    for i >= 0 {
        result[i] = alphabet[0]
        i -= 1
    }

    return string(result)
}

// Convenience function that just returns successive values from
// toPassword starting at start
func nextPassword(start, length int, alphabet []rune) func() string {
    n := start
    return func() string {
        result := toPassword(n, length, alphabet)
        n += 1
        return result
    }
}

func main() {
    for i := 5; i < 11; i++ {
        fmt.Println(toPassword(i, 2, []rune("ABCDE")))
    } // BA, BB, BC, BD, BE, CA

    // Now do the same thing using nextPassword
    np := nextPassword(5, 2, []rune("ABCDE"))
    for i := 0; i < 6; i++ {
        fmt.Println(np())
    } // BA, BB, BC, BD, BE, CA
}