| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1278 人关注过本帖
标题:摆个擂
只看楼主 加入收藏
Artless
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:4211
专家分:28888
注 册:2009-4-8
结帖率:100%
收藏
已结贴  问题点数:100 回复次数:22 
摆个擂
看到wp版的“大家晒一晒自己的代码啊”和小z版的“两位数乘三位数等于四位数并且这九个数都不重复”
就是“123456789”9个数,取2个组成一个两位数,取3个组成一个三位数,这两个数的积就是剩下的那四位数。
例12×483=5796
找出这些组合,用VB6实现。


[ 本帖最后由 Artless 于 2013-4-15 20:13 编辑 ]
2013-04-15 19:51
lowxiong
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:27
帖 子:652
专家分:3402
注 册:2008-5-7
收藏
得分:50 
擂台胜负标准是什么?运算速度还是代码简洁程度还是两者都有?
我先来个最笨的,抛砖引玉吧
Private Sub Command1_Click()
  Dim c(9) As Integer, i As Long, j As Long, k As Long, l As Boolean, b As String
  Me.Cls
  For i = 11 To 99
    For j = 111 To 999
      If i * j > 9999 Then Exit For  '加快执行速度
      b = i & j & (i * j)
      For k = 0 To 9
        c(k) = 0
      Next
      For k = 1 To Len(b)
        c(Val(Mid(b, k, 1))) = c(Val(Mid(b, k, 1))) + 1
      Next
      l = True
      For k = 1 To 9
        If c(k) <> 1 Then l = False
      Next
      If c(0) > 0 Then l = False
      If l Then Me.Print i & "*" & j & "=" & i * j
    Next
  Next
End Sub


[ 本帖最后由 lowxiong 于 2013-4-15 23:08 编辑 ]
2013-04-15 23:02
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
收藏
得分:50 
程序代码:
Option Explicit


Private Sub Command1_Click()
Dim i As Long, j As Long, m As Long          '二个循环变量及结果
Dim o As Long                       '判断用的循环变量
Dim k(1 To 9) As Long               '数字是否已用    '49 - 57
Dim s1 As String                    '连接结果用变量
Dim k2() As Byte, b1 As Boolean     '结果的BYTE数组和测试结果变量

Cls
Print "开始时间:" & Time
Debug.Print "开始时间:" & Time

For i = 12 To 98                                    '不重复的二位数,从 12 开始到 98

    For j = 123 To 987                              '不重复的三位数,从 123 开始到 987
        m = i * j
        If m < 10000 Then                           '结果要求为 4位数,也就是小于10000
            s1 = i & j & m
            k2 = StrConv(s1, vbFromUnicode)         '转化为 BYTE 数组
            For o = 1 To 9                          '计数数组初始化
                k(o) = 0
            Next o
            
            b1 = True                               '初始为真
            For o = 0 To 8
                If k2(o) = 48 Then                          '如果含零,则直接否决
                    b1 = False
                    Exit For
                End If
                k(k2(o) - 48) = k(k2(o) - 48) + 1           '个数累计
                If k(k2(o) - 48) > 1 Then                   '发现个数超过1,否决
                    b1 = False
                    Exit For
                End If
            Next o

            If b1 Then
                Print i & " * " & j & " = " & m             '输出结果
                Debug.Print i & " * " & j & " = " & m
            End If
        Else
            Exit For
        End If
    Next j
Next i
Print "结束时间:" & Time
Debug.Print "结束时间:" & Time

End Sub



开始时间:9:09:02
12 * 483 = 5796
18 * 297 = 5346
27 * 198 = 5346
28 * 157 = 4396
39 * 186 = 7254
42 * 138 = 5796
48 * 159 = 7632
结束时间:9:09:02


代码经过了优化,没去测试是否还存在我漏掉了的情况。

授人于鱼,不如授人于渔
早已停用QQ了
2013-04-16 09:17
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
开始时间:9:09:02
12 * 483 = 5796
18 * 297 = 5346
27 * 198 = 5346
28 * 157 = 4396
39 * 186 = 7254
42 * 138 = 5796
48 * 159 = 7632
结束时间:9:09:02



你这居然有7组答案

看来我的代码有bug啊

DO IT YOURSELF !
2013-04-16 09:21
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
收藏
得分:0 
2楼的代码,我也复制下来测试一下了,得到的也是7组答案。
2楼的代码,可以算是未优化的代码,应该可以把所有的答案都找出来。所有的数都去测试了。

但我在想:如果结果中含零,并且符合 要求时,2楼的代码会出会把这组结果也显示出来呢?     可惜假设不成立

------------------
发现有趣的东西
12 * 483 = 5796
42 * 138 = 5796

18 * 297 = 5346
27 * 198 = 5346

[ 本帖最后由 风吹过b 于 2013-4-16 09:33 编辑 ]

授人于鱼,不如授人于渔
早已停用QQ了
2013-04-16 09:32
lowxiong
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:27
帖 子:652
专家分:3402
注 册:2008-5-7
收藏
得分:0 
回复 5楼 风吹过b
If c(0) > 0 Then l = False,这句就是去0的,的确有一组中间为0的数据,不过大于9999,你的比我的总共少循环48次,再就是strconv执行效率不知道会比mid函数高多少,可用timegettime到毫秒级计算下具体执行时间就知道了。


[ 本帖最后由 lowxiong 于 2013-4-16 14:22 编辑 ]
2013-04-16 14:17
Artless
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:4211
专家分:28888
注 册:2009-4-8
收藏
得分:0 
2#耗时:343毫秒
3#耗时:110毫秒

无知
2013-04-16 14:48
lowxiong
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:27
帖 子:652
专家分:3402
注 册:2008-5-7
收藏
得分:0 
回复 7楼 Artless
我也测试了下,我的283毫秒,风兄107毫秒。楼主机器要换了,我08年的老本本比你的跑的都快。看来strconv函数执行效率高好多的。
2013-04-16 15:05
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
收藏
得分:0 
1、循环次数,我比 lowxiong 不此少 48 次。
   49毫秒, 11090 次。
   147毫秒,12784 次。
   在内循环第一第语句前计次。
   可惜 这个电脑不是自己的。

2、strconv 函数,不一定就执行效率高。
   关键在于,strconv 函数只需要调用一次,而你的需要调用 9次 mid 和 val 函数。 这个方面 不平等。


我的代码这段继续优化一下:
程序代码:
            For o = 0 To 8
                k2(o) = k2(o) - 48                  'val
                If k2(o) = 0 Then                          '如果含零,则直接否决
                    b1 = False
                    Exit For
                End If
                k(k2(o)) = k(k2(o)) + 1             '个数累计
                If k(k2(o)) > 1 Then                    '发现个数超过1,否决
                    b1 = False
                    Exit For
                End If
            Next o

优化的方向,减少无效计算过程,加一条命令直接生成结果数,精减原调用方式里4次引用时临时计算。由4次计算变1次计算,没有增加内存开销。

另一种优化
程序代码:
            For o = 1 To 9                          '计数数组初始化
                k(o) = False
            Next o
            
            b1 = True                               '初始为真
            For o = 0 To 8
                k2(o) = k2(o) - 48                  'val
                If k2(o) = 0 Then                          '如果含零,则直接否决
                    b1 = False
                    Exit For
                End If
                If k(k2(o)) Then                     '发现个数已用过,否决
                    b1 = False
                    Exit For
                Else
                    k(k2(o)) = True             '标记为用过
                End If
            Next o

优化方向,使用 逻辑型 数据变量,减少 比较运算符
-------------------
比较奇怪,一般来说 使用 boolean 应该比 比较符号要快,但从这二段代码运行结果来看,
基本没任何差异,也许循环次数太少的原因吧。

授人于鱼,不如授人于渔
早已停用QQ了
2013-04-16 15:49
lowxiong
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:27
帖 子:652
专家分:3402
注 册:2008-5-7
收藏
得分:0 
风兄分析的正确,我的大循环应该比风兄多循环99*999-86*864=24597次,但大循环次数不是影响速度的关键,关键是我的mid函数循环次数和我多了一个9次循环判断。改成下述代码后只需要86毫秒
Private Sub Command1_Click()
  Dim c(9) As Integer, i As Long, j As Long, k As Long, l As Boolean, b() As Byte, e As Integer
  Me.Cls
  t = timeGetTime
  For i = 11 To 99
    For j = 111 To 999
      If i * j > 9999 Then Exit For  '大于四位数的不用做,没有这一句就真多循环24597次以上
      b = i & j & i * j              '直接转换成byte数组
      For k = 0 To 9
        c(k) = 0                     '清空用于判断123456789使用一次的数组,未使用strconv,会是utf8,多用一倍内存
      Next
      l = True
      For k = 0 To UBound(b) Step 2
        e = b(k) - 48
        If e = 0 Or c(e) > 0 Then
          '这里是使用风兄的算法,一次判断完成,我的只是对标志+1,后再用一个9次循环判断
          l = False
          Exit For
        End If
        c(e) = c(e) + 1
      Next
      If l Then Me.Print i & "*" & j & "=" & i * j
    Next
  Next
  MsgBox timeGetTime - t    '显示耗时,此算法平均耗时86毫秒,少用20毫秒,但我的大循环仍比风兄的多,按风兄12-98,123-987,则需要75毫秒
End Sub

2013-04-16 18:18
快速回复:摆个擂
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.028569 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved