本帖最后由 zm900612 于 2011-4-24 11:29 编辑
若给定文本中不存在重字,这样比原始的40次变量替换更快,而且random的范围更加合理: | @echo off&setlocal enabledelayedexpansion&echo %time% | | for /f "useback skip=11" %%a in ("%~0") do set "str=!str!%%a" | | set str=@!str! | | for /l %%a in (0,1,16) do ( | | set /a a=!random!%%12+1 | | for %%b in (!a!) do call :str !str:~%%b,5! | | ) | | for /l %%a in (1 8 33) do echo !str:~%%a,8! | | echo %time%&pause>nul | | :str | | for /f "tokens=1* delims=%1" %%a in ("!str!") do set "str=%%a!str:*%1=!%1"&exit /b | | 我们去北京踢球吧 | | 快上那儿等着信号 | | 你不能离开大门口 | | 生与死就在一瞬间 | | 青春已从身边溜走COPY |
修改了“北大”为“北京”,16次call*5个字符的偏移范围,至少能把这40个字符循环两遍,保证随机性,同时random的取值范围降低,保证各部分字符串被随机选中的概率分布更为合理。
总之在效率和合理性上做了比较大的改进,相比原算法,最大的缺点就在于不支持重复字
现在发现,这似乎就是caruko说的“洗牌”算法,而且terse兄指出我绕弯了,其实只需要优化batman的代码就可以了...纯随机输出无重字文本时,这个大概是极限了(简化后的batman变量替换算法): | @echo off&setlocal enabledelayedexpansion&echo %time% | | for /f "skip=9 useback" %%a in ("%~0") do set "str=!str!%%a" | | for /l %%a in (0,1,40) do ( | | for %%b in (!random:~-1!) do ( | | for /f %%c in ("!str:~%%b,1!") do set str=!str:%%c=!%%c | | ) | | ) | | for /l %%a in (0 8 32) do echo !str:~%%a,8! | | echo %time%&pause>nul | | 我们去北京踢球吧 | | 快上那儿等着信号 | | 你不能离开大门口 | | 生与死就在一瞬间 | | 青春已从身边溜走COPY |
另有简化后的变量偏移的算法,效率和变量替换相差无几,支持重复字,但是代码多了两行: | ;@echo off&setlocal enabledelayedexpansion&echo %time% | | ;for /f "useback" %%a in ("%~0") do set str=!str!%%a | | ;for /l %%a in (40 -1 1) do ( | | ; set /a "ra=!random!%%%%a",n=ra+1 | | ; for /f "tokens=1* delims=@" %%b in ("!ra!@!n!") do ( | | ; set echo=!echo!!str:~%%b,1! | | ; set "str=!str:~0,%%b!!str:~%%c!" | | ; ) | | ;) | | ;for /l %%a in (0 8 32) do echo !echo:~%%a,8! | | ;echo %time%&pause>nul&exit | | 我们去北大踢球吧 | | 快上那儿等着信号 | | 你不能离开大门口 | | 生与死就在一瞬间 | | 青春已从身边溜走走COPY |
caruko提出的洗牌法,优点是可以轻易控制复杂程度和用时,缺点是经常洗不干净: | ;@echo off&setlocal enabledelayedexpansion&echo %time% | | ;for /f "useback" %%a in ("%~0") do set str=!str!%%a | | ;for /l %%a in (1 1 40) do ( | | ; set /a ra=!random:~-1!+5 | | ; for %%b in ("!ra!") do ( | | ; set str=!str:~-%%~b!!str:~5,-%%~b!!str:~0,5! | | ; ) | | ;) | | ;for /l %%a in (0 8 32) do echo !str:~%%a,8! | | ;echo %time%&pause>nul&exit | | 我们去北大踢球吧 | | 快上那儿等着信号 | | 你不能离开大门口 | | 生与死就在一瞬间 | | 青春已从身边溜走COPY |
以上几种算法都存在不易计算偏移量的先天缺陷,单独乱序输出时表现不错,但是若要同时计算偏移量,耗时将暴涨,此贴中另外三种在这方面则有优势:
常规算法就不提了,效率一般,也没什么艺术性。
读取自身输出作为输入的方案感觉已经无法再改进了,请见24楼terse代码。
最牛的应该是27楼neorobin的算法了,干净利落,浑然天成。 |