找回密码
 加入
搜索
查看: 24653|回复: 60

[效率算法] 练习003 - 顺序排列文本中的无序内容

 火... [复制链接]
发表于 2010-1-16 14:28:58 | 显示全部楼层 |阅读模式
本帖最后由 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:在实际应用方面,此题的解题思路也许用到的很少。纯属为了发散思维,有兴趣的就做下。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2010-1-16 15:37:01 | 显示全部楼层
难啊。。。我靠。。。能力问题啊!!!
发表于 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)

评分

参与人数 1金钱 +70 收起 理由
pusofalse + 70 学习了~!

查看全部评分

 楼主| 发表于 2010-1-16 15:48:20 | 显示全部楼层
本帖最后由 pusofalse 于 2010-1-16 16:09 编辑

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

评分

参与人数 1金钱 +79 收起 理由
pusofalse + 79 果真强大。

查看全部评分

发表于 2010-1-16 16:48:17 | 显示全部楼层
高,分割字符串那句实在是妙极了。
原始写法中的FileWriteLine,会使程序效率大大降低,因为如果要写入100 ...
pusofalse 发表于 2010-1-16 15:48



    多谢老大的指教~~
发表于 2010-1-16 17:25:20 | 显示全部楼层
这道题目实在有点难,不能为版主解决了,可不可以向AFAN版主学习一下。
发表于 2010-1-16 17:29:16 | 显示全部楼层
看看版主是怎么解决的
发表于 2010-1-16 17:31:55 | 显示全部楼层
这道题目实在有点难,不能为版主解决了,可不可以向AFAN版主学习一下。
xdcysten 发表于 2010-1-16 17:25



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

为了不影响他人的思维,因此也用了隐藏贴的形式~
发表于 2010-1-16 17:37:02 | 显示全部楼层
呵呵,这不是帮版主解决,pusofalse 超版是在给大家出题,每隔一段时间就有新的练习题,供大家学 ...
afan 发表于 2010-1-16 17:31


原来这样,不过还是感谢AFAN,受教了。
发表于 2010-1-16 19:28:58 | 显示全部楼层
本帖最后由 C.L 于 2010-1-16 20:35 编辑

这个题目,限制这么多,晕~
没看到afan做的,我也试一下,顺便回复,看看afan的作业:
$timestart = TimerInit ()
Dim $atemp [20],$afile [5][3]
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[0]=$i
WEnd

For $i=1 To $atemp[0]
        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][0]<$afile[$j][0] 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][2] <> "" Then
                $temp &= @crlf
        EndIf
Next
                
$timeend = TimerDiff ($timestart)
MsgBox (0,"运行时间:"&$timeend,$temp)

评分

参与人数 1金钱 +60 收起 理由
pusofalse + 60 学习了~

查看全部评分

发表于 2010-1-16 19:49:04 | 显示全部楼层
呵呵,看了各位大大的代码学到不少
发表于 2010-1-16 19:53:47 | 显示全部楼层
看不懂,先收藏慢慢学习
 楼主| 发表于 2010-1-16 20:22:27 | 显示全部楼层
本帖最后由 pusofalse 于 2010-1-16 20:24 编辑

回复 11# C.L


    果真是只用到了语句和运算符,学习了,很强大。 StringLower那两句没有意义啊,去掉之后效率还能提升。貌似代码还能够再简洁一点。
发表于 2010-1-16 20:37:26 | 显示全部楼层
回复 14# pusofalse

是的,那两句我测试的时候用,忘了删掉了。呵呵
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-11-15 17:25 , Processed in 0.094139 second(s), 29 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表