批处理之家's Archiver

batman 发表于 2009-11-23 01:04

【挑战】批处理实现摩尔斯码加解密

&&今天突然想起早几天看过的一部电影《风声》,里面描述的是地下**党是

如何利用摩尔斯密码跟敌人斗智斗勇的。在这里就不得简单先描述下摩尔斯码

了:摩尔斯码就是由双方以一定规律事先约定好的一组密码,它其实是由母本

和密文两部分组成的,而密文是根据母本上的排列规律来生成的。要破解这样

的密码,不得到母本基本上是不可能的。所以本人就想用批来模拟这一加密和

解密过程的实现。

    于是,我从网上找了个常用汉字简体表,再用批全部打乱生成了一个母本

homebook.txt如附件,母本中共有7176个汉字,分成了36版(部分),1-35版

每版10行,每行5列,每列4个字共200个字,36版也是如此排列,只是只有176

个字。而每个字就对应了一个四位的以“-”号格开的摩尔码(密文)如:段字

对应的摩尔码是30-9-1-1,30版9行1列第1个字(其实这一系列批处理比本挑战

题更麻烦)。

    现在我要求大家完成两个挑战:

    挑战一 根据homebook.txt将我给出的两组密文还原成原文(汉字),密

文如下(解密):

    1、17-5-5-1 8-2-2-4 17-10-4-4 9-8-3-1 3-2-5-3 21-7-1-2 15-9-1-3

    2、24-5-3-1 10-5-3-4 28-5-1-2 3-2-5-3 21-7-1-2 7-10-4-4 25-5-4-4

32-1-5-3 31-3-5-3 25-7-1-2 12-2-4-1 3-2-5-1

    挑战二 根据hommebook.txt将我给出的两句原文编译成密文(摩尔码),

原文如下(加密):

    1、我想他肯定知道这个地方有段好难走的路

    2、当敌人冲过来后你就拉响前面的警报

    要求不要生成临时文件,代码的效率要高,不得使用第三方工具,满分40

分,只完成一步不得分,以思路为重,酌情加分。

链接: [url]https://pan.baidu.com/s/1SqJmvTQXSSuGdhpK7bmsJw[/url] 提取码: n3g7

pusofalse 发表于 2009-11-23 02:31

此题挑战的绝对是批处理的执行效率,第2题实在想不出有什么高效的方法。
另外,30-9-1-1,30版9行1列第4个字,这里是否有误?

523066680 发表于 2009-11-23 08:49

以后可以用摩尔密码讲粗话不……


那个第一版的跟其他排的不一样,不统一哈
*******************************************************************
第1版
第1行: 蔡-町-铩-姬 摩-倡-词-洹 迪-龟-逵-骢 芄-粒-溧-唠 剸-炎-宜-淙


第2版
*******************************************************************
第1行: 砒-唳-珀-侉 珩-嗝-甥-锬 壅-初-邺-蹉 揍-琉-听-柲 憃-釉-链-椑

[[i] 本帖最后由 523066680 于 2009-11-23 08:52 编辑 [/i]]

batman 发表于 2009-11-23 08:59

回复 3楼 的帖子

是我大意,已修正,不过也不影响挑战。

523066680 发表于 2009-11-23 14:07

这次想找人合作……
从来没有过合作写批处理的感觉,唉~

[[i] 本帖最后由 523066680 于 2009-11-23 14:21 编辑 [/i]]

523066680 发表于 2009-11-23 15:15

回复 4楼 的帖子

是这样子的,我认为排列如果固定,解密的时候可以直接计算
来得到该字所在的行,会省很多事

[[i] 本帖最后由 523066680 于 2009-11-23 16:39 编辑 [/i]]

wankoilz 发表于 2009-11-23 16:40

我想解析密文相对简单,而且效率也应该比加密要高,方法我也用的很常规:[code]@echo off&setlocal enabledelayedexpansion
set "str1=17-5-5-1 8-2-2-4 17-10-4-4 9-8-3-1 3-2-5-3 21-7-1-2 15-9-1-3"
set "str2=24-5-3-1 10-5-3-4 28-5-1-2 3-2-5-3 21-7-1-2 7-10-4-4 25-5-4-4 32-1-5-3 31-3-5-3 25-7-1-2 12-2-4-1 3-2-5-1"
for /l %%i in (1,1,2) do (
   for %%j in (!str%%i!) do (
      for /f "delims=- tokens=1-4" %%k in ("%%j") do (
      call :search %%k %%l %%m %%n
      )
      set str=!str!!word!
   )
echo 密文:!str%%i!
echo 原文:!str!&set str=
)
echo.&pause>nul

:search
set/a line=(%1-1)*13+%2+2
set/a cols=%3+1
set tmp=0
for /f "delims=" %%i in (homebook.txt) do (
   set/a tmp+=1
   if !tmp!==!line! (
      for /f "tokens=%cols%" %%j in ("%%i") do (
         for /f "delims=- tokens=%4" %%k in ("%%j") do set word=%%k
         goto eof
      )
   )
)

:eof[/code]而加密感觉相对麻烦点,而且里面的几个“函数”效率都较低,尤其是算列数用了echo|find 这种方法,效率大减。但是搞了一中午累得很,头有点大,不想再改了,看其他兄弟的了:[code]@echo off&setlocal enabledelayedexpansion
set "str1=我想他肯定知道这个地方有段好难走的路"
set "str2=当敌人冲过来后你就拉响前面的警报"
for /l %%i in (1,1,2) do (
   for /f "delims=" %%j in ("!str%%i!") do (
   set str=%%j&call :split
   )
echo 原文:!str%%i!
echo 密文:!code!&set code=
)
echo.&pause>nul

:split
call :search !str:~0,1!
set code=!code! !singlecode!
set str=!str:~1!
if "!str!"=="" goto eof
goto split


:search
::为了避开汉字表中的"第,行,版"三个字,搜索时采用-*或*-的格式
findstr "\-%1" homebook.txt >nul&& call :transform \-%1
findstr "%1\-" homebook.txt >nul&& call :transform %1\-
goto eof

:transform
for /f "delims=: tokens=1-3" %%i in ('findstr/n "%1" homebook.txt') do (
   set tmpstr=%1&set tmpstr=!tmpstr:\-=!
   set 实际行数=%%i
   set tmp=%%j&set tmp=!tmp:第=!&set 版块行数=!tmp:行=!
   set count=
   for %%l in (%%k) do (
   set/a count+=1
   echo %%l|find "!tmpstr!">nul&&set 版块列数=!count!&&call :计算列中序数 !

tmpstr! %%l
   )
)
if !实际行数! lss 15 set 版块数=1
if !实际行数! geq 15 set/a 版块数=(!实际行数!-!版块行数!+12)/14
set singlecode=!版块数!-!版块行数!-!版块列数!-!列中序数!
goto eof


:计算列中序数
set tmpstr=%2&set tmpstr=!tmpstr:-= !
set count=
for %%i in (!tmpstr!) do (
set/a count+=1
if %%i==%1 set 列中序数=!count!
)

:eof[/code]

[[i] 本帖最后由 wankoilz 于 2009-11-26 15:45 编辑 [/i]]

batman 发表于 2009-11-23 17:27

要想提高效率,尽量不要用call,就本题而言,应该是不要出现一个call,
同时findstr也不要频繁使用。

pusofalse 发表于 2009-11-23 17:46

回复 7楼 的帖子

第一道题目还可以简化,应该活用skip。
第二道题目中,for %%i in (!tmpstr!) do (set/a count+=1&if %%i==%1 set 列中序数=!count!)
这个for语句出现了问题,因为每列有4个字,这个条件是已知的了,应该避免这种不必要的循环,用if ... else ... 代替。

wankoilz 发表于 2009-11-23 18:57

回复 9楼 的帖子

我也是看只有4个字,只循环4次,所以也就直接for了,是不大周密....

Seter 发表于 2009-11-23 21:01

[code]
@echo off&setlocal enabledelayedexpansion&set tmp=
for /f "delims=:" %%i in ('findstr /n * homebook.txt') do (
if defined tmp (
set tmp=
) else (
set tmp=1
set/ai+=1
set/ab!i!=%%i-1
)
)
for %%i in (17-5-5-1 8-2-2-4 17-10-4-4 9-8-3-1 3-2-5-3 21-7-1-2 15-9-1-3) do set t=%%i&call :f !t:-= !
echo.
for %%i in (24-5-3-1 10-5-3-4 28-5-1-2 3-2-5-3 21-7-1-2 7-10-4-4 25-5-4-4 32-1-5-3 31-3-5-3 25-7-1-2 12-2-4-1 3-2-5-1) do set t=%%i&call :f !t:-= !
echo.
pause&goto :eof
:f
set/ak=b%1+%2
set/at=%3*4-4+%4
for /f "skip=%k% tokens=%t% delims=- " %%i in (homebook.txt) do (
set/p=%%i<nul&goto :eof
)
[/code]

[[i] 本帖最后由 Seter 于 2009-11-23 22:02 编辑 [/i]]

523066680 发表于 2009-11-23 21:23

字典的文件名在开头定义,句子数量在开头定义


解密[code]@echo off
echo %time%
setlocal enabledelayedexpansion
set dict=dictionary.txt
set codex=2
set "code_1=17-5-5-1 8-2-2-4 17-10-4-4 9-8-3-1 3-2-5-3 21-7-1-2 15-9-1-3"
set "code_2=24-5-3-1 10-5-3-4 28-5-1-2 3-2-5-3 21-7-1-2 7-10-4-4 25-5-4-4 32-1-5-3 31-3-5-3 25-7-1-2 12-2-4-1 3-2-5-1"
for /l %%a in (1,1,%codex%) do (set all=!all! !code_%%a!)

::for遍历记录将要用到的行,避免每次都读取文本。
for /f "tokens=1,*" %%a in (%dict%) do (
   set now=%%a
   if "!now:~0,1!!now:~-1!"=="第版" (set "na=!now:第=!" &set "na=!na:版=!")
   if "!now:~0,1!!now:~-2!"=="第行:" (
      set "nb=!now:第=!" &set "nb=!nb:行:=!"
      for %%A in (!na!-!nb!) do (
        if not "!all: %%A=!"=="!all!" (
          set Line%%A=%%b
        )
      )
   )
)
::针对那两句
for /l %%a in (1,1,%codex%) do (
  for %%b in (!code_%%a!) do (
     set "now=%%b" &set "now=!now:-= !"
     set /a n=0
     for %%c in (!now!) do (set /a n+=1 &set num_!n!=%%c)
     set /a col=num_3*8-8+num_4*2-2
     for %%d in (!num_1!-!num_2!) do (set now=!Line%%d!)
     for %%d in (!col!) do (set /p=!now:~%%d,1!<nul)
  )
  echo,
)
echo %time%
pause[/code]加密

[code]@echo off
echo %time%
setlocal enabledelayedexpansion
set dict=dictionary.txt
set /a sayx=2
set "say_1=我想他肯定知道这个地方有段好难走的路"
set "say_2=当敌人冲过来后你就拉响前面的警报"
for /l %%a in (1,1,50) do (set one=111111!one!)
for /l %%a in (1,1,%sayx%) do (
set count=!say_%%a!#%one%
set count=!count:~0,300!
set count=!count:*#=!
set /a count%%a=300!count:1=-1!-1-1
for /l %%n in (0,1,!count%%a!) do (set "str_%%a=!str_%%a!!say_%%a:~%%n,1! ")
set strx_%%a=!str_%%a!
)
set /a na=0
::for遍历记录将要用到的行,避免每次都读取文本。
for /f "tokens=1,*" %%a in (%dict%) do (
   set now=%%a
   if "!now:~0,1!!now:~-1!"=="第版" (set /a na+=1,nb=0)
   if "!now:~0,1!!now:~-2!"=="第行:" (
      set /a nb+=1
      set now=%%b
      for /l %%A in (1,1,%sayx%) do (
         for %%B in (!str_%%A!) do (
         if not "!now:%%B=!"=="!now!" (
             set count=!now:*%%B=!#%one%
             set count=!count:~0,300!
             set count=!count:*#=!
             set /a count=300!count:1=-1!-1,count=40-count,nc=count/8+1,nd=count%%8+1,nd=nd/2
             for %%C in (!na!-!nb!-!nc!-!nd!) do (
               set strx_%%A=!strx_%%A:%%B=%%C!
             )
             set str_%%A=!str_%%A:%%B=!
         )
         )
      )
   )
)
for /l %%a in (1,1,%sayx%) do (echo !strx_%%a! &echo,)
echo %time%
pause

[/code]

[[i] 本帖最后由 523066680 于 2009-11-24 09:40 编辑 [/i]]

netbenton 发表于 2009-11-23 21:38

用call 的的方法之一

[code]@echo off&setlocal enabledelayedexpansion
set sati=!time!
set Ban=0
for /f "tokens=* delims=*" %%a in (homebook.txt) do (
        set str=%%a
        if "!str:~-1!" equ "版" (set /a Ban+=1) else (
                for /f "tokens=1,2,*" %%b in ("!ban! !str:-=!") do (set Ban%%b=!Ban%%b!%%d@)
        )
)
::前面读取母本到变量

for /f "tokens=*" %%a in (密文.txt) do (
        set 原文=
        for %%b in (%%a) do (
                for /f "tokens=1-4 delims=-" %%1 in ("%%b") do (
                        set/a hang=%%2-1
                        call :sub 原字 %%1 !hang! %%3 %%4
                        set 原文=!原文!!原字!
                )
        )
        echo;!原文!
)
::解密
echo;!sati!
echo;!time!
set sati=!time!


for /f "tokens=*" %%a in (原文.txt) do (
        set sour=%%a

        set/a z=8180,x=0,y=0
        for /l %%a in (1,1,14) do (set/a "y=(z-x)/2+x"
            for %%b in (!y!) do if "!sour:~%%b,1!" equ "" (set/a z=y) else (set/a x=y)
        )

        set 密文=
        echo !sour! [!x!]
        for /l %%b in (0,1,!x!) do (call :sub2 !sour:~%%b,1!)
        echo;!密文!
)
::加密
echo;!sati!
echo;!time!
pause

goto :eof

:sub
for /f "tokens=1-10 delims=@" %%0 in ("!Ban%2!") do (
        for /f "tokens=1-5" %%1 in ("%%%3") do (
                set "str=@%%%4"
                set %1=!str:~%5,1!
        )
)
goto :eof

:sub2
(
for /l %%a in (1,1,!ban!) do (
        if "!Ban%%a:%1=!" neq "!Ban%%a!" set str=!Ban%%a!&set zban=%%a
)
for /f "delims=%1" %%a in ("!str!") do (set str=%%a)

set/a z=8180,x=0,y=0
for /l %%a in (1,1,14) do (set/a "y=(z-x)/2+x"
    for %%b in (!y!) do if "!str:~%%b,1!" equ "" (set/a z=y) else (set/a x=y)
)

set/a zhang=x/26+1,x=x%%26,zlie=x/5+1,zzhi=x%%5+1
set 密文=!密文! !zban!-!zhang!-!zlie!-!zzhi!
goto :eof)[/code]

[[i] 本帖最后由 netbenton 于 2009-11-23 23:43 编辑 [/i]]

netbenton 发表于 2009-11-23 21:39

没有call 的方法之一

[code]
@echo off&setlocal enabledelayedexpansion
set sati=!time!
set Ban=0
for /f "tokens=* delims=*" %%a in (homebook.txt) do (
set str=%%a
if "!str:~-1!" equ "版" (set /a Ban+=1) else (
  for /f "tokens=1,2,*" %%b in ("!ban! !str:-=!") do (set Ban%%b=!Ban%%b!%%d@)
)
)
::前面读取母本到变量
for /f "tokens=*" %%a in (密文.txt) do (
set 原文=
for %%b in (%%a) do (
  for /f "tokens=1-4 delims=-" %%1 in ("%%b") do (
   for /f "tokens=1-10 delims=@" %%0 in ("!Ban%%1!") do (
    set v1=%%0&set v2=%%1&set v3=%%2&set v4=%%3&set v5=%%4&set v6=%%5&set v7=%%6&set v8=%%7&set v9=%%8&set v10=%%9
   )
   for /f "tokens=1-5" %%0 in ("!v%%2!") do (
    set v1=%%0&set v2=%%1&set v3=%%2&set v4=%%3&set v5=%%4
   )
   set "str=@!v%%3!"
   set 原文=!原文!!str:~%%4,1!
  )
)
echo;!原文!
)
::解密
echo;!sati!
echo;!time!
set sati=!time!
for /f "tokens=*" %%a in (原文.txt) do (
set sour=%%a
set/a z=8180,x=0,y=0
for /l %%a in (1,1,14) do (set/a "y=(z-x)/2+x"
     for %%b in (!y!) do if "!sour:~%%b,1!" equ "" (set/a z=y) else (set/a x=y)
)
set 密文=
echo !sour! [!x!]
for /l %%b in (0,1,!x!) do (
  for %%c in ("!sour:~%%b,1!") do (
   for /l %%d in (1,1,!ban!) do (
    if "!Ban%%d:%%~c=!" neq "!Ban%%d!" set str=!Ban%%d!&set zban=%%d
   )
   for %%d in ("!str:*%%~c=!") do set "str=!str:%%~d=!"
   
   set/a z=1000,x=0,y=0
   for /l %%a in (1,1,11) do (set/a "y=(z-x)/2+x"
    for %%b in (!y!) do if "!str:~%%b,1!" equ "" (set/a z=y) else (set/a x=y)
   )
   set/a zhang=x/26+1,x=x%%26,zlie=x/5+1,zzhi=x%%5
   set 密文=!密文! !zban!-!zhang!-!zlie!-!zzhi!
  )
)
echo;!密文!
)
::加密
echo;!sati!
echo;!time!
pause
goto :eof[/code]

[[i] 本帖最后由 netbenton 于 2009-11-23 23:43 编辑 [/i]]

Seter 发表于 2009-11-23 22:03

[code]@echo off&setlocal enabledelayedexpansion&set tmp=
for /f "delims=:" %%i in ('findstr /n * homebook.txt') do (
if defined tmp (
set tmp=
) else (
set tmp=1
set/ai+=1
set/a_%%i=!i!
)
)
call :f 安
pause&goto :eof
:f
for /f "tokens=1-2* delims=:第行" %%i in ('findstr /n /c:%1- homebook.txt') do set t=%%i&set k=%%j&set o=%%k
for /f "tokens=1-2* delims=:第行" %%i in ('findstr /n /c:-%1 homebook.txt') do set t=%%i&set k=%%j&set o=%%k
set o=!o:-= !
set o=!o:%1=? - !
set i=0&set s=1
for %%i in (%o%) do (
set/ai+=s
if "%%i"=="-" set s=0
)
set/ai-=1
set/ap=%i%%%4+1
set/ai=i/4+1
set/at=t-k
set t=!_%t%!
echo %t%-%k%-%i%-%p%
goto :eof[/code]抱歉,没时间写句子了

batman 发表于 2009-11-24 08:36

回复 15楼 的帖子

楼上的代码测试过没啊?运行有问题啊。

523066680 发表于 2009-11-24 08:54

netbenton非call 那个比我的快多了~

技术狂飙28了,遥望~

[[i] 本帖最后由 523066680 于 2009-11-24 09:02 编辑 [/i]]

wankoilz 发表于 2009-11-24 09:02

superman ......O(∩_∩)O哈哈~.......

batman 发表于 2009-11-24 10:51

&&针对以上的代码和方法小结一下:

    1、核心问题 毫无疑问此挑战在实现上难度并不大,也就是说有一定批处理基础的人都
可以解答出来。主要问题就是如何在解答出来的基础上最大限度地提升代码运行效率,这才
是我们所要考虑的核心问题,也是本人出题的初衷。
   
    2、方法分析 对于这样的较大数据比对,一般用到的有两种方法:一是变量赋值法,二
则是findstr查找法。而在这其中本人以为变量赋值法应该算是主流,因为用这种方法无论是
加密还是解密都是非常实用的,同时,这种方法能尽量避免call语法在代码中的出现(现在已
公认call语法在效率上存在问题),所以本人认为解此类问题,变量赋值法应列为首选。

    3、效率分析 本人仅以变量赋值法为例来谈谈如何尽量提高代码运行的效率,那么首先
我们应搞清楚代码在运行时最消耗时间的是哪一部分。像这样的问题,代码运行耗时基本在
变量赋值的过程中,而后面的解析变量给出结果基本都是在4毫秒左右(本机测试),所以如何
节省变量赋值的时间成了提高效率的关键。而针对本题的变更赋值一般会有三种方法:一是
将每个字赋值给变量,这就要构造7176个形如1-1-1-1的变量,这种方法有一个最大的优点
,因为它相当于建造了一个摩尔码和字一一对应的表,我们在解析码或字时只要代入这种对
应关系就可以得出结果,在连续转译大量编码和文字时,这样的方法是最快的也是最好的,
但相对于本题来讲,其效率则是最低的整个时间需要1秒以上(本机测试),同时也是对系统
资源的浪费;二是将母本的内容按行赋值给变量,这就只要构造359个形如1-1的变量,这种
方法能在很大程度上节约系统资源节省时间,整个赋值过程约为8毫秒(本机测试),但相对于
本题来讲,效率还是不如人意;三是将母本的内容按版(部分) 赋值给变量,只要构造1-36
36个变量,对系统资源的节省最高,赋值的效率肯定也是最快的了,但它也有缺点,那就是
整个赋值过程需要采用的技巧很高,同时因为cmd变量最大字节数的限制不适合大型段落的
情况,另外在解析取值给出结果时其过程也是较为复杂的,但无论如何,这种方法还是目前
所出现的解题方案中最好的。
   
    以上言论仅代表个人观点,还请有兴趣探讨的同志都发表下自己的看法。

[[i] 本帖最后由 batman 于 2009-11-24 10:59 编辑 [/i]]

523066680 发表于 2009-11-24 11:00

在思路已经是最简洁的时候,再怎么改,都是空间和时间的互换。
如果还能更节约时间空间,那么一定是思路,或者操作方式上做手脚

本人此时的观点

[[i] 本帖最后由 523066680 于 2009-11-24 11:06 编辑 [/i]]

523066680 发表于 2009-11-24 12:07

第二次写加密,换个方式,我就用findstr ,不过用一次。
在我的机子上平均 0.35秒[code]@echo off
echo %time%
setlocal enabledelayedexpansion
set dict=dictionary.txt
set /a sayx=2,act=1,b=1
set "say_1=我想他肯定知道这个地方有段好难走的路"
set "say_2=当敌人冲过来后你就拉响前面的警报"
for /l %%a in (1,1,50) do (set one=111111!one!)
for /l %%a in (1,1,%sayx%) do (
set count=!say_%%a!#%one%
set count=!count:~0,300!
set count=!count:*#=!
set /a count=300!count:1=-1!-1-1
for /l %%n in (0,1,!count!) do (set "str_%%a=!str_%%a!!say_%%a:~%%n,1! ")
set str=!str! !str_%%a!
)

for /f "tokens=1,2,* delims=: " %%a in ('findstr /n /r "%str%" %dict%') do (
set now=%%c
set now=!now:~1!
set /a na=%%a/14+1
set nb=%%b
set nb=!nb:第=!
set nb=!nb:行=!
      for /l %%A in (1,1,%sayx%) do (
         for %%B in (!str_%%A!) do (
         if not "!now:%%B=!"=="!now!" (
             for /l %%n in (0,1,39) do (if "!now:~%%n,1!"=="%%B" set /a count=%%n+1)
             set /a nc=count/8+1,nd=count%%8+1,nd=nd/2
             for %%C in (!na!-!nb!-!nc!-!nd!) do (
               set say_%%A=!say_%%A:%%B= %%C!
             )
             set str_%%A=!str_%%A:%%B=!
         )
         )
      )
)
for /l %%a in (1,1,%sayx%) do (echo !say_%%a! &echo,)
echo %time%
pause[/code]

[[i] 本帖最后由 523066680 于 2009-11-24 12:08 编辑 [/i]]

523066680 发表于 2009-11-24 14:11

呐,那个文字库收藏了,先来一句~

30-6-2-2 31-4-2-2 14-3-2-4 22-9-5-3 30-8-3-1 16-1-3-2 25-9-4-1 28-5-1-2 33-8-4-1 15-10-2-1, 19-9-4-2 11-6-3-3 21-10-1-1 36-8-5-4 10-1-3-4 26-2-3-1.

[[i] 本帖最后由 523066680 于 2009-11-24 14:16 编辑 [/i]]

Seter 发表于 2009-11-24 16:14

郁闷,可以的啊,你是哪个字?

batman 发表于 2009-11-24 16:18

呵呵,论坛是因为有了你们才很有气氛,另外5230666680 21楼这个findstr /n /r 用得好啊。

523066680 发表于 2009-11-24 17:34

回复 16楼 的帖子

15楼的代码这边测试还蛮正常的。
是对单个字转码的。

batman 发表于 2009-11-25 02:13

解密暂时还不能突破前面代码的效率,但加密肯定是突破了(本机测试11毫秒左右):[code]@echo off&setlocal enabledelayedexpansion
set "str1=我 想 他 肯 定 知 道 这 个 地 方 有 段 好 难 走 的 路"
set "str2=当 敌 人 冲 过 来 后 你 就 拉 响 前 面 的 警 报 行"
for /f "tokens=1-3 delims=:" %%a in ('findstr /n /r "%str1% %str2%" homebook.txt') do (
    set /a x=%%a%%14,a=%%a/14,b=%%b&set "vars=%%c"
    if !x! neq 0 set /a a+=1
    for %%a in (%str1% %str2%) do (
        if "!vars:%%a=!" neq "!vars!" (
           set "var=!vars!"
           set /a n=0&set "temp=!var:*%%a=!"
           if defined temp for /f "delims=" %%a in ("!temp!") do set "var=!var:%%a=!"
           set "var=!var:-= !"&for %%a in (!var!) do set /a n+=1
           set /a c=n/4+1,d=n%%4
           if !d! equ 0 set /a c-=1,d=4
           set "%%a=!a!-!b!-!c!-!d!"
        )
    )      
)
for %%a in (1 2) do (
    echo 原文:!str%%a!&set /p=密文:<nul
    for %%b in (!str%%a!) do set /p=!%%b! <nul
    echo.
)
pause>nul[/code]多亏了随风提出的set "var=!var:*字=!"的思路,用的是新homebook.txt(见楼下)

[[i] 本帖最后由 batman 于 2009-11-25 04:10 编辑 [/i]]

batman 发表于 2009-11-25 02:52

因为本人的失误使得findstr的运用受到限制,如查找“第、版、行”三个字时会出现错误,所以母本中的第?版,第?行中的汉字都应去掉,现重新上传母本上来,请各位对照修改自己的代码,对不起了。

523066680 发表于 2009-11-25 08:59

1。我的第二次加密测试过,遇到"版 第 行"不会错的。
   因为我for 的时候提取的参考字符是 "第x版" "第x行" 后面的那些信息,如果刚好是第x版 则提取为空
   接着我后面还有个判断 -- [字符] 是否存在于 [提取的参考字符]   于是只有遇到密文对应的行才会转换。
(另外本人大胆在前面使用字符串 1 化 +1 的方式来计算 字符串长度…… 虽然体积大,
    虽然耗时0.01 秒到0.02秒,不过为了前面设置的时候可以统一,我觉得值了。)

2。netbenton的经过测试遇到这三个字转换也正常的。

3。关于字典嘛,确实做适当的调整会比较方便批处理

4。batman代码测试新homebook.txt  本机0.30 秒 左右

[[i] 本帖最后由 523066680 于 2009-11-25 10:02 编辑 [/i]]

batman 发表于 2009-11-25 10:23

回复 28楼 的帖子

其实不修改母本也能正确处理“版、第、行”三个字,只是如上所说要大费一番周章,
如可以通过findstr正则来处理,但这样会影响到处理的效率,所以本人考虑再三还是将
母本进行了处理,以免不必要的麻烦。
另外,楼上的机子怎么比我的慢这么多。。。

[[i] 本帖最后由 batman 于 2009-11-25 11:43 编辑 [/i]]

netbenton 发表于 2009-11-25 12:24

28楼的肯定是双核cup

虽然批处理运行很“霸时间”,但是双核的cup不管怎样,一个进程只会用一个cup去执行。

[[i] 本帖最后由 netbenton 于 2009-11-25 12:27 编辑 [/i]]

页: [1] 2

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.