作为Learning-Go练习的一部分,我正在编写一个简单的暴力密码破解程序。
要生成在Python中使用字符A-E的所有可能的双字符密码,我会使用itertools.product():
from itertools import product
for permutation in product('ABCDE', repeat=2):
print permutation
但是,我在Go中努力做到这一点。
Other questions似乎与排列有关,这不是我想要的 。虽然Python文档包含该函数的示例实现,但我不知道如何将yield
翻译成Go。
我想我应该提到两个限制:
答案 0 :(得分:10)
你想要的基本上是一组自己的n-ary cartesian product。因此,对于所有3个字符的密码,您需要Prod(设置,设置,设置)。这可以迭代构造。首先构造n-1产品,然后为每个产品和初始集合的每个元素添加元素。例如,所有2个字符的密码 - > 3个字符的密码,其中唯一有效的字符是'a'或'b'。
"ab" = {a,b}
- > {(a,a),(a,b),(b,a),(b,b)}
- > {(a,a,a),(a,a,b),(a,b,a),(a,b,b),(b,a,a),(b,a,b),(b,b,a),(b,b,b)}
func NAryProduct(input string, n int) []string {
if n <= 0 {
return nil
}
// Copy input into initial product set -- a set of
// one character sets
prod := make([]string, len(input))
for i, char := range input {
prod[i] = string(char)
}
for i := 1; i < n; i++ {
// The bigger product should be the size of the input times the size of
// the n-1 size product
next := make([]string, 0, len(input)*len(prod))
// Add each char to each word and add it to the new set
for _, word := range prod {
for _, char := range input {
next = append(next, word + string(char))
}
}
prod = next
}
return prod
}
游乐场版:http://play.golang.org/p/6LhApeJ1bv
应该注意的是,这个解决方案还有很大的改进空间。如果要构造长度的所有密码,例如6-18,则为每个密码单独调用此方法将重新计算先前计算的集合。我会留下更好的版本给你。鉴于我向您展示的内容,修改代码以获取任意(n-m)ary产品并从中计算n-ary产品应该不会太困难。 (提示:考虑如何递归地执行此操作)
答案 1 :(得分:7)
例如,满足您的限制,
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)
}
}
输出:
AA
AB
AC
AD
AE
BA
BB
BC
BD
BE
CA
CB
CC
CD
CE
DA
DB
DC
DD
DE
EA
EB
EC
ED
EE