pusofalse 发表于 2010-1-16 14:28:58

练习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:在实际应用方面,此题的解题思路也许用到的很少。纯属为了发散思维,有兴趣的就做下。

kn007 发表于 2010-1-16 15:37:01

难啊。。。我靠。。。能力问题啊!!!

afan 发表于 2010-1-16 15:41:10

本帖最后由 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 15:48:20

本帖最后由 pusofalse 于 2010-1-16 16:09 编辑

高,分割字符串那句实在是妙极了。
原始写法中的FileWriteLine,会使程序效率大大降低,因为如果要写入100行内容,就要执行100次IO操作,IO操作是相当耗时的。先用FileOpen打开文件句柄之后再写入,可能效率会有所提高。最高效的写法是先用 &= 字符串连接符将所有要写入的内容连接为一个变量,最后只执行一次写入操作就好了。
赞佩至极,学习了!~

afan 发表于 2010-1-16 16:42:30

本帖最后由 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)

afan 发表于 2010-1-16 16:48:17

高,分割字符串那句实在是妙极了。
原始写法中的FileWriteLine,会使程序效率大大降低,因为如果要写入100 ...
pusofalse 发表于 2010-1-16 15:48 http://www.autoitx.com/images/common/back.gif


    多谢老大的指教~~

xdcysten 发表于 2010-1-16 17:25:20

这道题目实在有点难,不能为版主解决了,可不可以向AFAN版主学习一下。

landays 发表于 2010-1-16 17:29:16

看看版主是怎么解决的

afan 发表于 2010-1-16 17:31:55

这道题目实在有点难,不能为版主解决了,可不可以向AFAN版主学习一下。
xdcysten 发表于 2010-1-16 17:25 http://www.autoitx.com/images/common/back.gif


    呵呵,这不是帮版主解决,pusofalse 超版是在给大家出题,每隔一段时间就有新的练习题,供大家学习交流~

为了不影响他人的思维,因此也用了隐藏贴的形式~

xdcysten 发表于 2010-1-16 17:37:02

呵呵,这不是帮版主解决,pusofalse 超版是在给大家出题,每隔一段时间就有新的练习题,供大家学 ...
afan 发表于 2010-1-16 17:31 http://autoitx.com/images/common/back.gif

原来这样,不过还是感谢AFAN,受教了。

C.L 发表于 2010-1-16 19:28:58

本帖最后由 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)

yq314 发表于 2010-1-16 19:49:04

呵呵,看了各位大大的代码学到不少

catcher 发表于 2010-1-16 19:53:47

看不懂,先收藏慢慢学习

pusofalse 发表于 2010-1-16 20:22:27

本帖最后由 pusofalse 于 2010-1-16 20:24 编辑

回复 11# C.L


    果真是只用到了语句和运算符,学习了,很强大。 StringLower那两句没有意义啊,去掉之后效率还能提升。貌似代码还能够再简洁一点。

C.L 发表于 2010-1-16 20:37:26

回复 14# pusofalse

是的,那两句我测试的时候用,忘了删掉了。呵呵
页: [1] 2 3 4 5
查看完整版本: 练习003 - 顺序排列文本中的无序内容