找回密码
 加入
搜索
查看: 9092|回复: 26

[效率算法] 据说是小学数学题 大家有思路没?

 火... [复制链接]
发表于 2013-1-8 00:00:26 | 显示全部楼层 |阅读模式
昨天吃火锅的时候,有人无意提起,
大家拿起手机笔记本再那里算啊算  
心里想这个只能程序算吧。。。 看看周围没网吧,就算了。。。

好了,题来了

1-8 组成2个四位数,数字不重复,一个是另一个的4倍。
发表于 2013-1-8 08:22:22 | 显示全部楼层
回复 1# chinafla

看到离上班时间还有10来分钟,没啥事,正好拿这道题来找到一天coding的感觉!
我来先抛个砖头,看看能不能引来宝玉。10分钟的代码当然只考虑方法简单,不管效率高低,反正计算量也非常小,所以就用最烂的办法:枚举
首先这两个四位数,小的数先叫做数A,大的数叫做数B。
先来限定点条件,虽然不限定,多几个循环也能计算,但这样让现码农情何以堪呢!
① 数A的千位上只能为1,假设若不为1,则:
数A最小值为:2134
2134 * 4 = 8536  (重复了3,不合要求)
数A的次最小值为:2314
2314 * 4 = 9256  (这时已经超过数B可能的最大值8765,也不合要求,别的比2314大的数就更不可能了)

② 数A的个位上只能是 2, 3, 4, 6, 7, 8
因为1上面已经用过了,而5则由于5 * 4 = 20,从而让数B个位上出现了0,不合要求



MsgBox(0, "Result", Main())
Func Main()
        Local $iSmallNum, $aMidNum, $sResult = "Num1       Num2" & @CRLF & "--------------------" & @CRLF
        Local $aLastNum[6] = [2, 3, 4, 6, 7, 8]
        For $n = 0 To UBound($aLastNum) - 1
                $aMidNum = StringSplit(StringRegExpReplace("2345678", $aLastNum[$n], ""), "")
                For $i = 1 To $aMidNum[0]
                        For $j = 1 To $aMidNum[0]
                                If $i = $j Then ContinueLoop
                                $iSmallNum = Number("1" & $aMidNum[$i] & $aMidNum[$j] & $aLastNum[$n])
                                $iFlag = CompareString($iSmallNum)
                                If $iFlag Then $sResult &= $iSmallNum & "        " & $iSmallNum * 4 & @CRLF
                        Next
                Next
        Next
        Return $sResult
EndFunc

Func CompareString($iSmallNum)
        Local $aSplit
        $aSplit = StringSplit($iSmallNum * 4, "")
        For $i = 1 To $aSplit[0] - 1
                If $aSplit[$i] == 0 Or $aSplit[$i] == 9 Then Return 0
                For $j = $i + 1 To $aSplit[0]
                        If $aSplit[$i] == $aSplit[$j] Then Return 0
                Next
        Next        
        $aSplit = StringSplit($iSmallNum, "")
        For $i = 1 To $aSplit[0]
                $iFlag = StringInStr($iSmallNum * 4, $aSplit[$i])
                If $iFlag Then Return 0
        Next
        Return 1
EndFunc

评分

参与人数 2威望 +5 金钱 +60 贡献 +10 收起 理由
haijie1223 + 30 不是代码吸引我,而是佩服楼主的分析能力~
pusofalse + 5 + 30 + 10 学习了~

查看全部评分

发表于 2013-1-8 10:45:38 | 显示全部楼层
据上班已经开始 10分钟了,但是我刚来,cb的新闻不看了,说一下思路。

Python 代码:
import types
from timeit import Timer

def GetX():
    for n in range(4444,8888):
        b = n%4
        if b==0:
            a = n>>2
            temp = str(a) + str(n)
            t = set(temp)
            if len(t) == 8 and not( ('0' in t) or ('9' in t) ):
                print a , n
                exit
发表于 2013-1-8 10:51:38 | 显示全部楼层
本帖最后由 netegg 于 2013-1-8 11:10 编辑

回复 3# MicroBlue
happytc那个思路比较合适,这个重复计算的次数似乎多了,不过不懂python,也许处理过程没有重复计算
[au3]#include <Array.au3>

Dim $aArray[8] = [1, 2, 3, 4,5,6,7,8]
$aNewArray = _ArrayPermute($aArray, "") ;Using Default Parameters
For $i =  1 To $aNewArray[0]
        If Number(Stringleft($aNewArray[$i], 4))*4 > 8765 Then ExitLoop
        If Number(Stringleft($aNewArray[$i], 4))*4 = Number(StringRight($aNewArray[$i], 4)) Then
                ConsoleWrite($aNewArray[$i]& @cr)
        EndIf
Next
[/au3]
发表于 2013-1-8 12:35:07 | 显示全部楼层
回复 4# netegg


   
嗯, happytc 那个算法比我的好,效率比我的高。当时我也没多想,只想用 python 写出我的思路。
python 的内建函数太丰富了,一个 set()函数就解决了去重的问题,所以显得比较简洁。
发表于 2013-1-8 13:05:05 | 显示全部楼层
问题这么快就解决了,向算法达人学习
发表于 2013-1-8 13:48:08 | 显示全部楼层
好难哦,看看高手
发表于 2013-1-8 13:51:12 | 显示全部楼层
遇到此题,我越加感受到10进制计数方式的不便。某个外国网站说8进制在未来将会取代10进制,成为人们生活中普遍的计数方式,看来也有道理。
发表于 2013-1-8 14:59:55 | 显示全部楼层
想不到一到小学数学题这么难,代码学习了。
发表于 2013-1-8 15:52:18 | 显示全部楼层
没想太多只需要知道乘数最小数值是1234,最大不超过8765/4即可,速度有点慢,但是也能接受
$begin = TimerInit()
$result=""
For $i=1234 To Int(8765/4)
        StringRegExp(String($i&$i*4),'(\d).*?\1.*|[09]+',3)
        If @error Then $result=$result&String($i)&"----"&String($i*4)&@CRLF
Next
$dif = TimerDiff($begin)
MsgBox(0,$dif,$result)
                

评分

参与人数 2威望 +5 金钱 +45 贡献 +10 收起 理由
pusofalse + 5 + 25 + 10 都很厉害。StringRegExp的标志参数为何要用 ...
annybaby + 20 也不错,学习了~~

查看全部评分

发表于 2013-1-8 15:56:59 | 显示全部楼层
回复 8# pusofalse

我的代码时间比较固定 但是happytc 的代码时间总是变来变去的有时候比我快点有时候比我慢点
是我自己电脑的原因还是,他代码就是这样的。说实话我没看懂他代码,有点长,变量太多。
发表于 2013-1-8 19:02:38 | 显示全部楼层
回复 11# love5173

应该是你电脑原因了。因为计算量是完全固定的,不会改变的。所以计算时间也会是一样的。

可能是你电脑里的别的程序忽大忽小的占用了资源了。

不会吧,怎么会看不懂?前面我已经说明了呀,最最简单的想法了。
发表于 2013-1-8 19:07:19 | 显示全部楼层
回复 8# pusofalse

这个网站异想天开了
人类的习惯在很多时候是决定性力量。就象现在的键 盘布局一样,明明都知道它效率低。但谁又能把它改过来?因为大家没有感觉不够用,所以根本不会去改它。

我刚刚试了下用二进制做了下这题,由于计算量太小了,看不出它比十进制效率更高。
发表于 2013-1-8 22:19:53 | 显示全部楼层
回复 4# netegg
看了还是蛋哥的方法好理解。
发表于 2013-1-8 22:54:26 | 显示全部楼层
呵呵,和LOVE5173兄思路相同
local $time=TimerInit()
Local $output
local $k=4
For $i=1234 to Int(8765/$k)
        $num=$i*$k
    If Not StringRegExp($i&$num,'(.)[^\1]*(\1|0|9)',0) Then
                $output&=$i&"x4="&$num&@CRLF
        EndIf
Next
MsgBox(0,TimerDiff($time),$output)


另一个方法也没有什么新意

local $time=TimerInit()
Local $output
local $k=4
For $i=1234 to Int(8765/$k)
        $num=$i*$k
        if StringRegExp($num,'0|9',0) Then ContinueLoop
    If check($i,$num) Then
                $output&=$i&"====>"&$num&@CRLF
        EndIf
Next
MsgBox(0,TimerDiff($time),$output)

Func check($data1,$data2)
        local $string='12345678'
        $a=StringRegExpReplace($string,'['&$data2&']','')
        $b=StringRegExpReplace($string,'['&StringRegExpReplace($string,'['&$data1&']','')&']','')
        If $a=$b Then Return 1
EndFunc

评分

参与人数 2金钱 +60 收起 理由
491623644 + 10 学习了
happytc + 50 呵,正则大师来了,学习学习! 比我的代码 ...

查看全部评分

您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-11-15 14:56 , Processed in 0.084025 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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