字典生成算法实现(全排列实现)

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位以上大小写字符数字密码递归估计没什么机器能搞下来吧!但这土鳖办法却能!

posted @ 2023-01-21 00:21  一朵野生菌  阅读(53)  评论(0编辑  收藏  举报