练习003 - 顺序排列文本中的无序内容
本帖最后由 pusofalse 于 2010-2-26 23:38 编辑顺序排列文本中的无序内容。
出题目的:
掌握文本处理、变量赋值、排列数据。
题解:
有一文本a.txt内容如下(请下载附件):
:true
true??
assign!
这里是一空行。
:false
false??
:loop
L$***,G$***
:test
^^~!!%%^^
false??
:M$
M$###,M-obj其中a.txt中的内容是未知的,知道的条件如下:
1、文中有n个段落(n>1),每个段落的起始符号是冒号:。
以上内容中,有5个段落,分别是:true、 :false、 :loop、 :test、 :M$
2、每个段落中有m条内容(m>0),每行内容的第一个字符总是不为冒号:。
以上内容中,:true段落的内容为true??和assign!。
3、文本中的第一行总是段落名称。没有一个段落与另一个段落的名称相同,但内容可能有所相同。
4、段落与段落之间,总是有一空行连接。
5、未知文本中最后一行是否为空行。
目的:将以上内容按照段落名称的字母先后顺序排列(大写字母M位于小写字母t前),输出如下::false
false??
:loop
L$***,G$***
:M$
M$###,M-obj
:test
^^~!!%%^^
false??
:true
true??
assign!只是排列段落,段中的内容不能改变。
要求:
不生成任何临时文件;效率高效,以上的5个段落,程序从运行至输出超过0.5秒即为淘汰。
拓展:
如果完成了上述要求,再禁止调用除下列以外的函数,只用语句和运算符号和各类宏变量完成上述要求。
1、TimerInit、TimerDiff - 计算运行时间。
2、FileRead或FileReadLine - 读取文本内容。
3、StringRegExp或StringRegExpReplace - ???
4、Msgbox - 输出结果。
5、除上述5个函数,不能再调用其他任何内置函数、自定义函数。
加分规则:
20-80分不等。
1、能够正确输出结果,加分20。
2、不生成任何临时文件、代码高效,运行时间不超过0.5s,最少30分。
3、完成拓展的要求,加分70~80。
4、如果你调用StringRegExp或StringRegExpReplace,仅是为了判断一行是否是段落行,将从加分中减去10分。
5、视代码思路加分。
PS:在实际应用方面,此题的解题思路也许用到的很少。纯属为了发散思维,有兴趣的就做下。
难啊。。。我靠。。。能力问题啊!!! 本帖最后由 afan 于 2010-1-18 02:11 编辑
试下~#include <Array.au3>
local $ts = TimerInit(), $strNew, $i
local $str = FileRead('a.txt')
local $sS = StringSplit($str, @CRLF & @CRLF, 3)
If @error = 0 Then
_ArraySort($sS)
For $i = 0 To UBound($sS) - 1
If $sS[$i] <> '' Then $strNew &= $sS[$i] & @CRLF & @CRLF
Next
EndIf
MsgBox(0, '完成耗时(s):' & TimerDiff($ts) / 1000, $strNew) 本帖最后由 pusofalse 于 2010-1-16 16:09 编辑
高,分割字符串那句实在是妙极了。
原始写法中的FileWriteLine,会使程序效率大大降低,因为如果要写入100行内容,就要执行100次IO操作,IO操作是相当耗时的。先用FileOpen打开文件句柄之后再写入,可能效率会有所提高。最高效的写法是先用 &= 字符串连接符将所有要写入的内容连接为一个变量,最后只执行一次写入操作就好了。
赞佩至极,学习了!~ 本帖最后由 afan 于 2010-1-18 02:11 编辑
拓展了下……
Dim $ts = TimerInit(), $strNew, $i, $x
Dim $str = FileRead('a0.txt')
Dim $sR = StringRegExp($str, '(?s):.+?\r\n\r\n', 3)
If @error Then Exit
For $x = 0 To UBound($sR) - 1
For $i = UBound($sR) - 1 To 1 Step -1
If $sR[$i] < $sR[$i - 1] Then
$atmp = $sR[$i]
$sR[$i] = $sR[$i - 1]
$sR[$i - 1] = $atmp
EndIf
Next
$strNew &= $sR[$x]
Next
MsgBox(0, '完成耗时(s):' & TimerDiff($ts) / 1000, $strNew)
高,分割字符串那句实在是妙极了。
原始写法中的FileWriteLine,会使程序效率大大降低,因为如果要写入100 ...
pusofalse 发表于 2010-1-16 15:48 http://www.autoitx.com/images/common/back.gif
多谢老大的指教~~ 这道题目实在有点难,不能为版主解决了,可不可以向AFAN版主学习一下。 看看版主是怎么解决的 这道题目实在有点难,不能为版主解决了,可不可以向AFAN版主学习一下。
xdcysten 发表于 2010-1-16 17:25 http://www.autoitx.com/images/common/back.gif
呵呵,这不是帮版主解决,pusofalse 超版是在给大家出题,每隔一段时间就有新的练习题,供大家学习交流~
为了不影响他人的思维,因此也用了隐藏贴的形式~ 呵呵,这不是帮版主解决,pusofalse 超版是在给大家出题,每隔一段时间就有新的练习题,供大家学 ...
afan 发表于 2010-1-16 17:31 http://autoitx.com/images/common/back.gif
原来这样,不过还是感谢AFAN,受教了。 本帖最后由 C.L 于 2010-1-16 20:35 编辑
这个题目,限制这么多,晕~
没看到afan做的,我也试一下,顺便回复,看看afan的作业:
$timestart = TimerInit ()
Dim $atemp ,$afile
Dim $m=0,$n=0
$i=1
While 1
$sLine = FileReadLine ("a.txt",$i)
If @error = -1 Then ExitLoop
$atemp[$i]=$sLine
$i+=1
$atemp=$i
WEnd
For $i=1 To $atemp
If $atemp[$i] <> "" Then
$afile[$m][$n]=$atemp[$i]
$n+=1
Else
$m+=1
$n=0
ContinueLoop
EndIf
Next
For $i=0 To 4
For $j=0 To 4
If $afile[$i]<$afile[$j] Then
For $m=0 To 2
$temp = $afile[$i][$m]
$afile[$i][$m] = $afile[$j][$m]
$afile[$j][$m] = $temp
Next
EndIf
Next
Next
$temp = ""
For $i=0 To 4
For $j=0 To 2
$temp &= $afile[$i][$j]&@CRLF
Next
If $afile[$i] <> "" Then
$temp &= @crlf
EndIf
Next
$timeend = TimerDiff ($timestart)
MsgBox (0,"运行时间:"&$timeend,$temp)
呵呵,看了各位大大的代码学到不少 看不懂,先收藏慢慢学习 本帖最后由 pusofalse 于 2010-1-16 20:24 编辑
回复 11# C.L
果真是只用到了语句和运算符,学习了,很强大。 StringLower那两句没有意义啊,去掉之后效率还能提升。貌似代码还能够再简洁一点。 回复 14# pusofalse
是的,那两句我测试的时候用,忘了删掉了。呵呵