找回密码
 加入
搜索
楼主: pusofalse

[效率算法] 趣味正则:用正则匹配3的倍数

 火... [复制链接]
发表于 2010-3-15 21:34:09 | 显示全部楼层
本帖最后由 rolaka 于 2010-3-15 21:47 编辑
$number = 1200000
$array = StringSplit($number, "", 2)
$string = ""
For $i = 0 To UBound($array)-1
        For $n = 1 To $array[$i]
                $string &= "."
        Next
Next
If StringRegExp($string, '^(...)+$') Then
        MsgBox(0, 0, $number & ' 是3的倍数')
Else
        MsgBox(0, 0, $string & ' 不是3的倍数')
EndIf
山寨升级版.................................(afan的 1200000会出错...)
T_T 正则本身不支持运算 好郁闷


极限测试
$time = TimerInit()
$number = 999999999999999999
$array = StringSplit($number, "", 2)
$string = ""
For $i = 0 To UBound($array)-1
        For $n = 1 To $array[$i]
                $string &= "."
        Next
Next
If StringRegExp($string, '^(...)+$') Then
        MsgBox(0, TimerDiff($time), $number & ' 是3的倍数')
Else
        MsgBox(0, TimerDiff($time), $string & ' 不是3的倍数')
EndIf

评分

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

查看全部评分

发表于 2010-3-15 21:56:13 | 显示全部楼层
山寨升级版.................................(afan的 1200000会出错...)
T_T 正则本身不支持运算 好郁闷
...
rolaka 发表于 2010-3-15 21:34



    这升级版好啊~
发表于 2010-3-15 23:16:20 | 显示全部楼层
本帖最后由 gapkiller 于 2010-3-15 23:22 编辑

把$iNum转换一下
原理, 能被3整除的数, 其所有位数上数的和能被三整除
While $iNum>10
        $s=StringSplit($iNum,'',0)
        $iNum=0
        For $i=1 To $s[0]
                $iNum += $s[$i]
        Next
WEnd
最后只剩下一个数啦(3,6,9),哈哈哈哈,我随便正则.....
发表于 2010-3-15 23:24:18 | 显示全部楼层
本帖最后由 C.L 于 2010-3-15 23:33 编辑

我也来个升级版,极限测试效率本机运行为0.25ms.
$time = TimerInit ()
$num = 999999999999999999
$bit = "---------"
$temp = ""
For $i = 1 To StringLen ($num)
        $temp &= StringLeft($bit,StringMid($num,$i,1))
Next

If StringRegExp($temp, '^(---)+$') Then
        MsgBox(0, TimerDiff($time), $num & ' 是3的倍数')
Else
        MsgBox(0, TimerDiff($time), $num & ' 不是3的倍数')
EndIf
发表于 2010-3-16 09:09:10 | 显示全部楼层
本帖最后由 bob 于 2010-3-16 09:10 编辑

以前学正则时候,看过一个蹊跷的解决办法,这背后藏有一个暴力算法

因AU3长度限制,很长的数字是没办法的
$a = 9999999999
$array = StringRegExp(_DecToBinary($a), '^1((10*1)|(01*0))*10*$', 3)

If @Error = 0 Then Msgbox(0, "判断结果", $a & "是3的倍数")

Func _DecToBinary($sDecStr, $iLength = 0) ;十进制转换为二进制
        Local $sBinStr = ""
        If NOT StringRegExp($sDecStr, "^\d+$") Then Return SetError(1, 0, "")

        If $sDecStr > 1125899906842622 Then Return SetError(1, 0, "")
        While $sDecStr > 0
                $sBinStr = Mod($sDecStr, 2) & $sBinStr
                $sDecStr = Int($sDecStr / 2)
        WEnd

        While StringLen($sBinStr) < $iLength
                $sBinStr = "0" & $sBinStr
        WEnd

        Return $sBinStr
EndFunc   ;==>_DecToBinary

评分

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

查看全部评分

 楼主| 发表于 2010-3-16 10:29:35 | 显示全部楼层
回复 20# bob


    学习了,有限状态机,目前我也是用了这种解法~ - -
发表于 2010-3-16 10:43:08 | 显示全部楼层
以前学正则时候,看过一个蹊跷的解决办法,这背后藏有一个暴力算法

因AU3长度限制,很长的数 ...
bob 发表于 2010-3-16 09:09



    转换为二进制再判断,真是高~ 学习了~
发表于 2010-3-16 16:17:05 | 显示全部楼层
以前学正则时候,看过一个蹊跷的解决办法,这背后藏有一个暴力算法

因AU3长度限制,很长的数 ...
bob 发表于 2010-3-16 09:09



    转换成二进制搜...好办法啊 但 au3字符串长了就崩
发表于 2010-3-16 21:48:22 | 显示全部楼层
afan的方法数字不能太大,因为字符串长途是有限制的,这样能相当大:
Local $Num = InputBox("判断数字能否被3整除", "请输入一个数字", "")
$len = StringLen($Num)

Local $str
For $n = 1 To $len
        $iNum = StringMid($Num, $n, 1)
        For $i = 1 To $iNum
                $str &= '.'
        Next
Next
If StringRegExp($str, '^(...)+$') Then
        MsgBox(0, 0, $Num & ' 是3的倍数')
Else
        MsgBox(0, 0, $Num & ' 不是3的倍数')
EndIf
发表于 2010-3-16 22:02:19 | 显示全部楼层
回复 24# vuivui


    我那仅是个思路而已,并没推敲~ 因并不符合题目的主题思想…… 呵呵  
发表于 2010-3-17 09:28:42 | 显示全部楼层
afan 真不愧为 超版 ! 不但人品不错! 思维也越级厉害 !

评分

参与人数 1金钱 +10 收起 理由
afan + 10 超级过奖… 我只是个打杂的...

查看全部评分

发表于 2010-7-5 23:58:35 | 显示全部楼层
本帖最后由 foboy 于 2010-7-18 01:25 编辑

大家别白忙活了,&也是运算符。具体请看帮助文件:【语言相关 - 运算符】一节。运算符并不只有简单的加减乘除。
先分析一下:
一个数字钟如果只含有0 3 6 9 这几个数字,肯定是能被3整除。下面分析其他数字的情况
数字:必须含有其他什么数字时才能被3整除
1:2 5 8
2:1 4 7
4:2 5 8
5:1 4 7
7:2 5 8
8:1 4 7
现在发现一个很有规律的东西,即 1 4 7 和2 5 8 正好分成固定的2组,如果一个数字含有一个[147]中的数字,则他必须也含有一个[258]中的数字才能被三整除。换句话说,只要一个数字里含有[147]的个数和[258]的个数相等就可以。根据这个规律我写了一个只有一行代码的函数:
Func test($_num)
        Return StringCompare(UBound(StringRegExp($_num, '[147]', 3)), UBound(StringRegExp($_num, '[258]', 3)))
EndFunc   ;==>test
能被三整除时返回0,不能被三整除时返回非0
该函数比较[147] [258]的个数时用StringCompare而不用=号的原因是:=号也属于运算符。
大家别怪俺太较真啊。

评分

参与人数 3金钱 +110 贡献 +5 收起 理由
sleep365 + 20 学习了,这个是数学的高手啊。
Duvet + 30 + 5
pusofalse + 60 学习了,很强大。

查看全部评分

发表于 2010-7-6 01:03:48 | 显示全部楼层
回复 1# pusofalse


    27楼才是正解。完全符合要求,而且简单,准确。比数点的诸多办法更胜一筹。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-5-16 08:02 , Processed in 0.087267 second(s), 21 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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