字典生成算法实现(全排列实现)
package main // @Title main.go // @Description 入口文件 // @Author xiao // @Update none import ( "flag" "fmt" "log" ) // 字典常量 const ( lowerCaseChars = "abcdefghijklmnopqrstuvwxyz" // 小写字母 upperCaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // 大写字母 nums = "0123456789" // 数字 //nums = "01" // 数字 halfWidthChars = "`~!@#$%^&*()_+=-{}[]:\";’|<>?,./" // 半角标点 fullWidthChars = "`~!#¥%^&*()_+=-{}[]:";'\|<>?,./,。" // 全角标点 //fullWidthChars = "`~" blankspace = " " // 空格 ) var wordLen int = 1 var lower bool var upper bool var num bool var hf bool var fl bool var blank bool // 默认情况下字典范围哦 var dicts string = "" var runeDicts []rune // @title init // @descroption 参数解析 // @auth xiao 2023/01/13 // @update none // @param // @return func init() { flag.IntVar(&wordLen, "len", 1, "需要生成的单词长度") flag.BoolVar(&lower, "lower", false, "使用小写字母") flag.BoolVar(&upper, "upper", false, "使用大写字母") flag.BoolVar(&num, "num", false, "使用0-9数字") flag.BoolVar(&hf, "hf", false, "使用半角标点集合") flag.BoolVar(&fl, "fl", false, "使用全角表单集合") flag.BoolVar(&blank, "bl", false, "使用空格") flag.Parse() } func buildDicts() { if lower { dicts = dicts + lowerCaseChars } if upper { dicts = dicts + upperCaseChars } if num { dicts = dicts + nums } if hf { dicts = dicts + halfWidthChars } if fl { dicts = dicts + fullWidthChars } if blank { dicts = dicts + blankspace } if wordLen <= 0 { log.Fatal("参数设置错误!") } if len(dicts) == 0 { log.Fatal("所选字典为空!") } runeDicts = []rune(dicts) } // wheel type wheel struct { charIndex int prewheel *wheel lastwheel bool } // @title gen // @descroption 遍历生成本齿轮中的字符序列 // @auth xiao 2023/01/14 // @update none // @param word *string 字典结果 // @return 字典结果 func (cg *wheel) gen(word *string) (*string, bool) { if cg.charIndex == len(runeDicts) { cg.charIndex = 0 cg.notifyPreWheel() return word, true } if cg.charIndex < len(runeDicts) { *word = string(runeDicts[cg.charIndex]) + *word if cg.lastwheel { cg.charIndex++ } } return word, false } // @title notifyPreWheel // @descroption 通知齿轮中前一个齿轮滑动到下一个字符序列 // @auth xiao 2023/01/14 // @update none // @param // @return void func (w *wheel) notifyPreWheel() { if w.prewheel != nil { w.prewheel.charIndex++ } } var wheels = make([]*wheel, 0) func buildDictWheels() { for i := 0; i < wordLen; i++ { if i == 0 { wheels = append(wheels, &wheel{prewheel: nil, charIndex: 0, lastwheel: false}) } else { w := wheels[i-1] wheels = append(wheels, &wheel{prewheel: w, charIndex: 0, lastwheel: false}) } } wheels[len(wheels)-1].lastwheel = true } // @title main // @descroption main // @auth xiao 2023/01/13 // @update none // @param // @return 0 执行成功 1 执行异常 func main() { buildDicts() log.Println("当前所选字符集合:", dicts) buildDictWheels() for { stopflag := true skipWord := false word := "" for i := len(wheels) - 1; i >= 0; i-- { _, stop := wheels[i].gen(&word) if stop { skipWord = true } stopflag = stop && stopflag } if stopflag { break } if !skipWord { fmt.Println(word) } } }
没什么好说的,直接贴代码吧,见过水表么?水表里面就是N多个齿轮组合在一起,最后一个齿轮转一圈带动前面一个齿轮转一下,当所有齿轮转到最大的时候表示所有字符组合遍历完一遍。代码实现每一位密码相当于一个水表齿轮。
#./dictgen -len 2 -num -lower > 1.txt #cat 1.txt aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au av aw ax ay az a0 a1 a2 a3 a4 a5 a6 ...
为什么不用递归来生成密码?8位以上大小写字符数字密码递归估计没什么机器能搞下来吧!但这土鳖办法却能!
本文来自博客园,作者:一朵野生菌,转载请注明原文链接:https://www.cnblogs.com/xmy20051643/p/17063429.html