chinafla 发表于 2013-1-8 00:00:26

据说是小学数学题 大家有思路没?

昨天吃火锅的时候,有人无意提起,
大家拿起手机笔记本再那里算啊算
心里想这个只能程序算吧。。。 看看周围没网吧,就算了。。。

好了,题来了

1-8 组成2个四位数,数字不重复,一个是另一个的4倍。

happytc 发表于 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 =
        For $n = 0 To UBound($aLastNum) - 1
                $aMidNum = StringSplit(StringRegExpReplace("2345678", $aLastNum[$n], ""), "")
                For $i = 1 To $aMidNum
                        For $j = 1 To $aMidNum
                                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 - 1
                If $aSplit[$i] == 0 Or $aSplit[$i] == 9 Then Return 0
                For $j = $i + 1 To $aSplit
                        If $aSplit[$i] == $aSplit[$j] Then Return 0
                Next
        Next       
        $aSplit = StringSplit($iSmallNum, "")
        For $i = 1 To $aSplit
                $iFlag = StringInStr($iSmallNum * 4, $aSplit[$i])
                If $iFlag Then Return 0
        Next
        Return 1
EndFunc

MicroBlue 发表于 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

netegg 发表于 2013-1-8 10:51:38

本帖最后由 netegg 于 2013-1-8 11:10 编辑

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

Dim $aArray =
$aNewArray = _ArrayPermute($aArray, "") ;Using Default Parameters
For $i =1 To $aNewArray
        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

MicroBlue 发表于 2013-1-8 12:35:07

回复 4# netegg


   
嗯, happytc 那个算法比我的好,效率比我的高。当时我也没多想,只想用 python 写出我的思路。
python 的内建函数太丰富了,一个 set()函数就解决了去重的问题,所以显得比较简洁。

xiaowo 发表于 2013-1-8 13:05:05

问题这么快就解决了,向算法达人学习

huangke 发表于 2013-1-8 13:48:08

好难哦,看看高手

pusofalse 发表于 2013-1-8 13:51:12

遇到此题,我越加感受到10进制计数方式的不便。某个外国网站说8进制在未来将会取代10进制,成为人们生活中普遍的计数方式,看来也有道理。

king8462 发表于 2013-1-8 14:59:55

想不到一到小学数学题这么难,代码学习了。

love5173 发表于 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.*|+',3)
        If @error Then $result=$result&String($i)&"----"&String($i*4)&@CRLF
Next
$dif = TimerDiff($begin)
MsgBox(0,$dif,$result)
               

love5173 发表于 2013-1-8 15:56:59

回复 8# pusofalse

我的代码时间比较固定 但是happytc 的代码时间总是变来变去的有时候比我快点有时候比我慢点
是我自己电脑的原因还是,他代码就是这样的。说实话我没看懂他代码,有点长,变量太多。

happytc 发表于 2013-1-8 19:02:38

回复 11# love5173

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

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

不会吧,怎么会看不懂?前面我已经说明了呀,最最简单的想法了。

happytc 发表于 2013-1-8 19:07:19

回复 8# pusofalse

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

我刚刚试了下用二进制做了下这题,由于计算量太小了,看不出它比十进制效率更高。

xms77 发表于 2013-1-8 22:19:53

回复 4# netegg
看了还是蛋哥的方法好理解。

3mile 发表于 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
页: [1] 2
查看完整版本: 据说是小学数学题 大家有思路没?