前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >VBA实现排列组合(可重复)

VBA实现排列组合(可重复)

作者头像
xyj
发布2021-10-20 16:59:44
2.5K0
发布2021-10-20 16:59:44
举报
文章被收录于专栏:VBA 学习VBA 学习

数学里的排列组合是不能重复选择数据的,这里实现一种可以重复选择数字的排列组合。

这么一个功能的使用场景可以是这样的,比如设置了一个6位数字的密码,但是忘记了,有一个程序可以快速的去测试密码,这时候就需要逐个去测试可能的密码。

这种时候的问题就转换为从0-9这10个数字中,选取6个数字了,个数很简单,就是10的6次方,100万个,那么如何快速的生成这100万个数字呢?

使用VBA来实现的话,最简单的方法自然是使用循环,100万个数字太大了,这里简化一下,从4个数字中选3个:

代码语言:javascript
复制
Sub PLZH()
    Dim src(4 - 1) As String
    
    src(0) = "1"
    src(1) = "2"
    src(2) = "3"
    src(3) = "4"
    
    Dim Result() As String
    ReDim Result(4 ^ 3 - 1, 0) As String
    
    Dim Count As Long
    Dim tmp As String
    
    Dim n0 As Long, n1 As Long, n2 As Long
    For n0 = 0 To 4 - 1
        For n1 = 0 To 4 - 1
            For n2 = 0 To 4 - 1
                tmp = src(n0) & src(n1) & src(n2)
                Result(Count, 0) = tmp
                Count = Count + 1
            Next
        Next
    Next
    
    Range("A1").Resize(Count, 1).Value = Result
End Sub

这样就快速的得到了64个排列组合。

很显然,如果需要选6个数字,那么就得用6个循环,这个程序虽然很简单的,但是不能通用。

如果很设计一个功能,只要输入数据源,以及需要选择的数据个数,就能够得到结果就非常的方便了。

其实这个算法可以根据数字的加法来设计:

代码语言:javascript
复制
'有点类似加法的10进1的方法
'对于排列的结果,m个位置相对于ArrKeys下标的取值范围都是1-n(注意下标0的情况)
'初始m个位置都取下标0
'm个位置的第1个位置开始逐步加1,直到>n的时候,进一位,第2位变为1,并且本身变为了0
'然后继续从0到n,继续进位,直到第2位也>n,进位,第3位变为1
'循环到m的位置>n停止

'函数返回结果的个数,-1表示出错了
'为了和数字的加法类似,程序是从下标m-1开始逐步加1的
Function GetPermutation(ArrKeysZeroBase() As String, m As Long, Result() As String) As Long
    Dim n As Long
    
    n = UBound(ArrKeysZeroBase) - LBound(ArrKeysZeroBase) + 1
    If m = 0 Then
        GetPermutation = -1
        Exit Function
    End If
    
    GetPermutation = n ^ m
    ReDim Result(GetPermutation - 1) As String
    
    '记录m个位置的index
    Dim p() As Long
    '记录当前正在处理的p()index
    Dim pp As Long
    ReDim p(m - 1) As Long
    
    '记录临时的数据,方便用join函数
    Dim tmp() As String
    Dim i As Long
    ReDim tmp(m - 1) As String
    
    Dim Count As Long
    Do
        '提取结果数据
        For i = 0 To m - 1
            tmp(i) = ArrKeysZeroBase(p(i))
        Next
        Result(Count) = VBA.Join(tmp, "")
        Count = Count + 1
        
        pp = m - 1
        p(pp) = p(pp) + 1
        
        'p数组元素的最大值是n-1
        Do While p(pp) = n
            '进位
             p(pp) = 0
             pp = pp - 1
             If pp = -1 Then Exit Function
             p(pp) = p(pp) + 1
        Loop
        
    Loop While 1
End Function

测试:

代码语言:javascript
复制
Sub TestPermutation()
    Dim arr(3) As String
    
    arr(0) = "1"
    arr(1) = "2"
    arr(2) = "3"
    arr(3) = "4"
    
    Dim Result() As String
    GetPermutation arr, 3, Result
    
    Range("A1").Resize(UBound(Result) + 1, 1).Value = Application.WorksheetFunction.Transpose(Result)
End Sub
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 VBA 学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档