Algorithm 批处理脚本中暴力算法的优化
此批处理脚本的目的是实现一个简单的暴力算法,以便生成所有可能的10个字母数字字符长的字符串,并且在一个字符和下一个字符之间不重复Algorithm 批处理脚本中暴力算法的优化,algorithm,batch-file,brute-force,Algorithm,Batch File,Brute Force,此批处理脚本的目的是实现一个简单的暴力算法,以便生成所有可能的10个字母数字字符长的字符串,并且在一个字符和下一个字符之间不重复 set alphanumerics=a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,0,1,2,3,4,5,6,7,8,9 for %%l in (%alphanumerics%) do ( for
set alphanumerics=a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,0,1,2,3,4,5,6,7,8,9
for %%l in (%alphanumerics%) do (
for %%m in (%alphanumerics%) do (
for %%n in (%alphanumerics%) do (
for %%o in (%alphanumerics%) do (
for %%p in (%alphanumerics%) do (
for %%q in (%alphanumerics%) do (
for %%r in (%alphanumerics%) do (
for %%s in (%alphanumerics%) do (
for %%t in (%alphanumerics%) do (
for %%u in (%alphanumerics%) do (
if %%u NEQ %%t (
if %%t NEQ %%s (
if %%s NEQ %%r (
if %%r NEQ %%q (
if %%q NEQ %%p (
if %%p NEQ %%o (
if %%o NEQ %%n (
if %%n NEQ %%m (
if %%m NEQ %%l (
echo %%l%%m%%n%%o%%p%%q%%r%%s%%t%%u >> output.txt
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
此脚本的主要问题是,完成任务所需的时间量仍然非常巨大,因为尽管各种if
分支正在过滤最终输出,但for
块仍然计算了数千个无效组合。因此,我真的很想改进整个脚本,以最好的方式使用所有计算能力而不浪费它。我在考虑在并行进程之间分配整个算法。或者,一个基于2的字符串生成器:在第一步中,脚本可以生成并存储所有可能的字符对
for %%x in (%alphanumerics%) do (
for %%y in (%alphanumerics%) do (
if %%y NEQ %%x (
echo.%%x%%y >> output.txt
)
)
)
然后,在第二步中,它可以使用先前生成的对匹配它们,生成四个字符长的字符串;然后,八个字符长,等等
for /f %%v in (output.txt) do (
set firstvar=%%v
set firstchar=!firstvar:~1!
;First character of the listed couples
for /f "skip=1" %%w in (output.txt) do (
set secondvar=%%w
set secondchar=!secondvar:~0,1!
;Last character of the listed couples
if !secondchar! NEQ !firstchar! (
echo.!firstvar!!secondvar! >> output_2.txt
)
)
)
总之,我如何改进此算法以节省时间?下面的解决方案比您的解决方案快得多,也许这是在批处理文件中执行此操作的最快方法
@echo off
setlocal EnableDelayedExpansion
set "alphanumerics=a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,X,Y,Z,0,1,2,3,4,5,6,7,8,9"
(for %%a in (%alphanumerics%) do (
for %%b in (%alphanumerics%) do if %%a neq %%b (
for %%c in (%alphanumerics%) do if %%b neq %%c (
for %%d in (%alphanumerics%) do if %%c neq %%d (
for %%e in (%alphanumerics%) do if %%d neq %%e (
for %%f in (%alphanumerics%) do if %%e neq %%f (
for %%g in (%alphanumerics%) do if %%f neq %%g (
for %%h in (%alphanumerics%) do if %%g neq %%h (
for %%i in (%alphanumerics%) do if %%h neq %%i (
for %%j in (%alphanumerics%) do if %%i neq %%j (
echo %%a%%b%%c%%d%%e%%f%%g%%h%%i%%j
)
)
)
)
)
)
)
)
)
)) > output.txt
下面的解决方案比您的解决方案快得多,也许这是在批处理文件中执行此操作的最快方法
@echo off
setlocal EnableDelayedExpansion
set "alphanumerics=a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,X,Y,Z,0,1,2,3,4,5,6,7,8,9"
(for %%a in (%alphanumerics%) do (
for %%b in (%alphanumerics%) do if %%a neq %%b (
for %%c in (%alphanumerics%) do if %%b neq %%c (
for %%d in (%alphanumerics%) do if %%c neq %%d (
for %%e in (%alphanumerics%) do if %%d neq %%e (
for %%f in (%alphanumerics%) do if %%e neq %%f (
for %%g in (%alphanumerics%) do if %%f neq %%g (
for %%h in (%alphanumerics%) do if %%g neq %%h (
for %%i in (%alphanumerics%) do if %%h neq %%i (
for %%j in (%alphanumerics%) do if %%i neq %%j (
echo %%a%%b%%c%%d%%e%%f%%g%%h%%i%%j
)
)
)
)
)
)
)
)
)
)) > output.txt
您可以提前排除可能的邻居匹配,如下所示。请注意,
alphanumerics
变量中的密码种子被剪切,输出仅限于每千分之一个字,仅用于演示目的
@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
set "alphanumerics=a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,X,Y,Z,0,1,2,3,4,5,6,7,8,9,"
set "alphanumerics=a,b,c,d,e,A,B,C,D,E,0,1,2,3,4,5,"
set "alphanumerics=a,b,c,A,B,C,0,1,2,"
set "alphanumerics=a,b,A,B,0,1,"
set /A "_counter=0"
rem > output.txt (
for %%l in (%alphanumerics%) do (
set "al=!alphanumerics:%%l,=!"
for %%m in (!al!) do (
set "am=!alphanumerics:%%m,=!"
for %%n in (!am!) do (
set "an=!alphanumerics:%%n,=!"
for %%o in (!an!) do (
set "ao=!alphanumerics:%%o,=!"
for %%p in (!ao!) do (
set "ap=!alphanumerics:%%p,=!"
for %%q in (!ap!) do (
set "aq=!alphanumerics:%%q,=!"
for %%r in (!aq!) do (
set "ar=!alphanumerics:%%r,=!"
for %%s in (!ar!) do (
set "as=!alphanumerics:%%s,=!"
for %%t in (!as!) do (
set "at=!alphanumerics:%%t,=!"
for %%u in (!at!) do (
rem echo %%l%%m%%n%%o%%p%%q%%r%%s%%t%%u
set /A "_counter+=1"
set /A "_inter=_counter %% 100000"
if !_inter! EQU 0 echo %%l%%m%%n%%o%%p%%q%%r%%s%%t%%u !_counter!
)
)
)
)
)
)
)
)
)
)
echo %_counter%
ENDLOCAL
goto :eof
然而,我担心我们没有足够的时间(以及磁盘空间)来完成您的任务,因为迭代次数呈指数增长,甚至更快
有3479922
可能的密码(在几分钟内找到)和set“alphanumerics=a,b,a,b,0,1”
。为了回顾增长时间(和空间),这里摘录了使用set“alphanumerics=a,b,c,a,b,c,0,1,2,
(密码种子中只有三个字符c,c,2,
更多):经过一千万次迭代后仍然领先a
acbcB2A21A 9600000
acbAcA2ABc 9700000
acbA121A1A 9800000
acbCB1aBCA 9900000
acb0bcAcba 10000000
acb01abCA1 10100000
acb1c0AcbA 10200000
acb12cABC2 10300000
acb2BacB2b 10400000
acAba0Bc02 10500000
^CacAbAB1bCb 10536175
Terminate batch job (Y/N)? y
您可以提前排除可能的邻居匹配,如下所示。请注意,
alphanumerics
变量中的密码种子被剪切,输出仅限于每千分之一个字,仅用于演示目的
@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
set "alphanumerics=a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,X,Y,Z,0,1,2,3,4,5,6,7,8,9,"
set "alphanumerics=a,b,c,d,e,A,B,C,D,E,0,1,2,3,4,5,"
set "alphanumerics=a,b,c,A,B,C,0,1,2,"
set "alphanumerics=a,b,A,B,0,1,"
set /A "_counter=0"
rem > output.txt (
for %%l in (%alphanumerics%) do (
set "al=!alphanumerics:%%l,=!"
for %%m in (!al!) do (
set "am=!alphanumerics:%%m,=!"
for %%n in (!am!) do (
set "an=!alphanumerics:%%n,=!"
for %%o in (!an!) do (
set "ao=!alphanumerics:%%o,=!"
for %%p in (!ao!) do (
set "ap=!alphanumerics:%%p,=!"
for %%q in (!ap!) do (
set "aq=!alphanumerics:%%q,=!"
for %%r in (!aq!) do (
set "ar=!alphanumerics:%%r,=!"
for %%s in (!ar!) do (
set "as=!alphanumerics:%%s,=!"
for %%t in (!as!) do (
set "at=!alphanumerics:%%t,=!"
for %%u in (!at!) do (
rem echo %%l%%m%%n%%o%%p%%q%%r%%s%%t%%u
set /A "_counter+=1"
set /A "_inter=_counter %% 100000"
if !_inter! EQU 0 echo %%l%%m%%n%%o%%p%%q%%r%%s%%t%%u !_counter!
)
)
)
)
)
)
)
)
)
)
echo %_counter%
ENDLOCAL
goto :eof
然而,我担心我们没有足够的时间(以及磁盘空间)来完成您的任务,因为迭代次数呈指数增长,甚至更快
有3479922
可能的密码(在几分钟内找到)和set“alphanumerics=a,b,a,b,0,1”
。为了回顾增长时间(和空间),这里摘录了使用set“alphanumerics=a,b,c,a,b,c,0,1,2,
(密码种子中只有三个字符c,c,2,
更多):经过一千万次迭代后仍然领先a
acbcB2A21A 9600000
acbAcA2ABc 9700000
acbA121A1A 9800000
acbCB1aBCA 9900000
acb0bcAcba 10000000
acb01abCA1 10100000
acb1c0AcbA 10200000
acb12cABC2 10300000
acb2BacB2b 10400000
acAba0Bc02 10500000
^CacAbAB1bCb 10536175
Terminate batch job (Y/N)? y
如果每个位置(邻居限制)有61个字符,但第一个不受前一个字符限制,则必须生成
(61^9)*62 = 725037057755716742 combinations.
每秒生成1000000个组合您需要22991年才能生成完整列表,并且需要7728 PB的存储空间,每个值后面有10个字符和CRLF终止符
但是
注1已编辑脚本。正如JosefZ指出的,原始代码失败了,因为批处理文件中的字符串替换不区分大小写(我忘了)。该代码已被修改,以解决问题,包括一个能够区分上下字符的填充符,但不包括在输出中。无论如何,在答案的末尾可以找到原来的错误代码
@echo关闭
setlocal enableextensions disabledelayedexpansion
设置“字母数字=,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z”
设置“字母数字=%alphanumerics%,!!(A,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,T,T,U,U,U,U,U,U,U,U,U,U,N,U,O,U,P,S,U,T,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U
设置“alphanumerics=%alphanumerics%,0,1,2,3,4,5,6,7,8,9”
设置“u173=”
仅用于测试的rem:4*(3^9)=78732个组合
设置“字母数字=,a,b,a,b!”
延迟扩展
对于(!字母数字中的%%a!
)在(!alphanumerics:^,%%a^=中为%%b执行操作!
)在(!alphanumerics:^,%%b^=中为%%c执行操作!
)在(!alphanumerics:^,%%c^=中为%%d执行操作!
)在(!alphanumerics:^,%%d^=中为%%e执行操作!
)在(!alphanumerics:^,%%e^=中为%%f执行操作!
)在(!alphanumerics:^,%%f^=!
)在(!alphanumerics:^,%%g^=中为%%h执行操作!
)在(!alphanumerics:^,%%h^=!
)在(!alphanumerics:^,%%i^=!
)做回显(%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j
执行代码时,!\u!
将包含在可替换参数的中,但由于变量\u
为空,它将不包含在echo
命令的输出中,并在延迟扩展解析器阶段用空字符串替换
这是答案中的原始(错误)代码。未正确处理大写/小写字符串替换
@echo关闭
setlocal enableextensions enabledelayedexpansion
rem更改为包含起始逗号
设置“字母数字=,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,r,s,t,u,w,x,y,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,V,x,y,z,0,1,2,3,4,5,7,8,9”
对于%%a in(%alphanumerics%)
)在(!alphanumerics:^,%%a^=中为%%b执行操作!
)在(!alphanumerics:^,%%b^=中为%%c执行操作!
)在(!alphanumerics:^,%%c^=中为%%d执行操作!
)在(!alphanumerics:^,%%d^=中为%%e执行操作!
)在(!alphanumerics:^,%%e^=中为%%f执行操作!
)在(!alphanumerics:^,%%f^=!
)在(!alphanumerics:^,%%g^=中为%%h执行操作!
)在(!alphanumerics:^,%%h^=!
)执行%%j英寸(!字母数字:^