我有5个项目可以按任何唯一顺序放置,我想将一个唯一订单的值(数字)逐个存储到变量中。例如:
用户输入:7
然后i_Int = 7
应该给我
v_Var = 1
等一下
v_Var = 3
等一下
v_Var = 2
等一下
v_Var = 4
等一下
v_Var = 5
下面的数据列出了5个项目的所有可能的排列,其中第一行列出了排列#,我将不会有这些数据使事情变得简单。
1 1 2 3 4 5
2 1 2 3 5 4
3 1 2 4 3 5
4 1 2 4 5 3
5 1 2 5 3 4
6 1 2 5 4 3
7 1 3 2 4 5
8 1 3 2 5 4
9 1 3 4 2 5
10 1 3 4 5 2
...
111 5 3 2 1 4
112 5 3 2 4 1
113 5 3 4 1 2
114 5 3 4 2 1
115 5 4 1 2 3
116 5 4 1 3 2
117 5 4 2 1 3
118 5 4 2 3 1
119 5 4 3 1 2
120 5 4 3 2 1
这是一个返回1,...,n
等级的i
的排列的函数:
Function Unrank(ByVal n As Long, ByVal rank As Long, Optional lb As Long = 1) As Variant
Dim Permutation As Variant
Dim Items As Variant
ReDim Permutation(lb To lb + n - 1)
ReDim Items(0 To n - 1)
Dim i As Long, j As Long, k As Long, q As Long
Dim fact As Long
For i = 0 To n - 1
Items(i) = i + 1
Next i
rank = rank - 1
j = lb
For i = n - 1 To 1 Step -1
fact = Application.WorksheetFunction.fact(i)
q = Int(rank / fact)
Permutation(j) = Items(q)
'slide items above q 1 unit to left
For k = q + 1 To i
Items(k - 1) = Items(k)
Next k
j = j + 1
rank = rank Mod fact
Next i
'place last item:
Permutation(lb + n - 1) = Items(0)
Unrank = Permutation
End Function
默认情况下,它将结果作为基于1的数组返回。要使其基于0,请使用Unrank(5,7,0)
之类的调用。作为测试:
Sub test()
'fills A1:A120 with the permutations of 1,2,3,4,5
Dim i As Long
For i = 1 To 120
Cells(i, 1).Value = Join(Unrank(5, i), " ")
Next i
End Sub
13!
太大而无法容纳Long
变量,所以代码在n=14
时会抛出一个未捕获的错误。我使用的算法取决于使用相关因子进行模运算的能力,因此在VBA中没有简单的修复。请注意,您可以轻松调整代码,以便将一系列项目传递给置换,而不是总是置换1-n。该算法会破坏数组Items
,因此这样的调整将涉及创建一个基于0的(以便模块化算法计算出来)传递数组的副本。