[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

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

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

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

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

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

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

解密过程的实现。

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

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

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

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

评分人数

***共同提高***

回复 3楼 的帖子

是我大意,已修正,不过也不影响挑战。
***共同提高***

TOP

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

TOP

回复 15楼 的帖子

楼上的代码测试过没啊?运行有问题啊。
***共同提高***

TOP

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

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

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

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

评分人数

***共同提高***

TOP

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

TOP

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

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

评分人数

***共同提高***

TOP

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

TOP

回复 28楼 的帖子

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

[ 本帖最后由 batman 于 2009-11-25 11:43 编辑 ]
***共同提高***

TOP

是时候把它弄出来了

&&针对这一摩尔码加解密,本人弄了个vbs+批版的,当然为了方便先生成了一个list.txt。

该工具可以同时将转译结果显示出来并输入到剪贴板中,你只要在文本中右键或ctrl+v就

可以输出结果到文本。
  1. dim path,strinput,stroutput,counter
  2. counter=2
  3. do
  4. on error resume next
  5. if counter=1 then
  6.    exit do
  7.    else
  8.    strinput=inputbox("请输入要转译的文字或编码,退出请点取消","转译工具")
  9.    if strinput=false then
  10.       wscript.quit
  11.       else
  12.       set wshshell=createobject("wscript.shell")
  13.       path=wshshell.currentdirectory
  14.       set objie=createobject("internetexplorer.application")
  15.       set objfso=createobject("scripting.filesystemobject")
  16.       set objtext=objfso.opentextfile("temp.txt",2,true)
  17.       objtext.write strinput
  18.       objtext.close
  19.       set objtext=objfso.opentextfile("temp.bat",2,true)
  20.       objtext.writeline "@echo off&setlocal enabledelayedexpansion"
  21.       objtext.writeline "set /p input=<temp.txt&del /q temp.txt&set "&chr(34)&"k= "&chr(34)
  22.       objtext.writeline "if "&chr(34)&"%input:-=%"&chr(34)&" neq "&chr(34)&"%input%"&chr(34)&" set "&chr(34)&"k="&chr(34)&"&set "&chr(34)&"str=%input%"&chr(34)&"&goto next"
  23.       objtext.writeline ":lp"
  24.       objtext.writeline "set "&chr(34)&"str=%str% %input:~,1%"&chr(34)
  25.       objtext.writeline "set "&chr(34)&"input=%input:~1%"&chr(34)
  26.       objtext.writeline "if defined input goto lp"
  27.       objtext.writeline ":next"
  28.       objtext.writeline "for /f "&chr(34)&"tokens=1,2"&chr(34)&" %%a in ('findstr /r "&chr(34)&"%str%"&chr(34)&" list.txt') do ("
  29.       objtext.writeline "if "&chr(34)&"%k%"&chr(34)&" equ "&chr(34)&""&chr(34)&" ("
  30.       objtext.writeline "set "&chr(34)&"%%a=%%b"&chr(34)
  31.       objtext.writeline ") else ("
  32.       objtext.writeline "set "&chr(34)&"%%b=%%a"&chr(34)
  33.       objtext.writeline "))"
  34.       objtext.writeline "for %%a in (%str%) do set /p=!%%a!%k%<nul>>temp.txt"
  35.       objtext.close
  36.       wshshell.run "temp.bat",0
  37.       wscript.sleep 1000
  38.       set objtext=objfso.opentextfile("temp.txt",1)
  39.       stroutput=objtext.readall
  40.       objtext.close
  41.       objie.navigate("about:blank")
  42.       objie.document.parentwindow.clipboarddata.setdata "text", stroutput
  43.       objie.quit
  44.       wshshell.popup stroutput,2,"转译结果"
  45.       objfso.deletefile("temp.bat")
  46.       objfso.deletefile("temp.txt")
  47.       set objfo=nothing
  48.       set objie=nothing
  49.       set swshshell=nothing  
  50.       end if
  51.    end if
  52. loop
复制代码
注:转译的时间长是因为防出错加入了wscript.sleep 1000,你可以修改这个1000的值来加快速度
***共同提高***

TOP

回复 37楼 的帖子

高手一出手,就知有没有,terse的代码一直有着简洁高效的特点,学习了。

但加密时,各字之间完全可以真接用空格格开,就不用折半法来判断字符长度了。
***共同提高***

TOP

返回列表