Combinations / Permutations VBA

lrobbo314

Well-known Member
Joined
Jul 14, 2008
Messages
3,948
Office Version
  1. 365
Platform
  1. Windows
I know this has been covered, and believe me, I've looked around, but I haven't found a solution yet.

I am trying to figure out how to write a recursive function that will give every possible combination given a certain group size.

So, if the array is {1,2,3,4,5} and the group size is 3, I will get

1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5

And if I bump the group size to 4, I will get

1 2 3 4
1 2 3 5
1 2 4 5
1 3 4 5
2 3 4 5

I've tried to diagram out the sequence of events, as in table below, to try and figure out the code, but I've just been banging my head against the table.

So, if someone could help out and show me how this would work as a recursive VBA solution. Recursion has always made my head hurt.


CDEFGHI
1171628319Results
21716283191, 7
31716283191, 16
41716283191, 28
51716283191, 3
61716283191, 19
71716283197, 16
81716283197, 28
91716283197, 3
101716283197, 19
1117162831916, 28
1217162831916, 3
1317162831916, 19
1417162831928, 3
1517162831928, 19
161716283193, 19
171716283191, 7, 16
181716283191, 7, 28
191716283191, 7, 3
201716283191, 7, 19
211716283191, 16, 28
221716283191, 16, 3
231716283191, 16, 19
241716283191, 28, 3
251716283191, 28, 19
261716283191, 3, 19

<caption>
</caption><colgroup><col style="width: 54px"><col width="133"><col width="149"><col width="133"><col width="133"><col width="133"><col width="133"><col width="133"></colgroup><tbody>
</tbody>
 

Excel Facts

Move date out one month or year
Use =EDATE(A2,1) for one month later. Use EDATE(A2,12) for one year later.
You seem to really be interested in this question. I found a thread you started over 2 years ago with the same question.

https://www.mrexcel.com/forum/excel-questions/907809-recursive-vba-combinations.html

In any event, here's one way to do it:

Code:
Sub CallRecur()
Dim keys()


    Cells.ClearContents
    myitems = Array(1, 2, 3, 4, 5)
    groupsize = 3
    
    ReDim keys(0 To groupsize)
    keys(0) = 0
    
    Call Recur(myitems, UBound(myitems) + 1, groupsize, 0, keys)
    
    
End Sub


Sub Recur(ByVal MyArray, ByVal n, ByVal gs, ByVal d, ByVal keys)


    
    For i = keys(d) + 1 To n
        keys(d + 1) = i
        If d + 1 = gs Then
            r = Cells(Rows.Count, "A").End(xlUp).Row + 1
            For j = 1 To gs
                Cells(r, j) = MyArray(keys(j) - 1)
            Next j
        Else
            Call Recur(MyArray, n, gs, d + 1, keys)
        End If
    Next i


End Sub

Obviously, you can populate the array in many different ways, and you can print out the results in many different ways. Note that when defining the array as I did, the lowest index is 0, which is why there's some +1/-1 in the code. Since I'm just printing the results out on a sheet, this will error out when you hit the maximum number of rows per sheet. But I suspect you'll run out of stack space long before that.

Hope this gives you some ideas though.
 
Upvote 0
Same basic algorithm, but I used a couple of public variables to clean up the code, which should be easier to follow now. I also only write the results to the worksheet once, which should make it faster. Note the "" entry at the start of the array.

Code:
Public Results As Object
Public MyItems As Variant

Sub CallRecur()

    Set Results = CreateObject("Scripting.Dictionary")
    MyItems = Array("", "dog", "cat", "horse", "iguana", "parakeet")
    
    Call Recur(UBound(MyItems), 3, 0, 1, "")
    
    Cells.ClearContents
    Range("A1").Resize(Results.Count).Value = WorksheetFunction.Transpose(Results.keys)
    Range("A:A").TextToColumns OtherChar:="|"
    
End Sub

' n is the number of items, gs is group size, d is depth,
' curix is the current index, comb is the combination so far
Sub Recur(ByRef n, ByRef gs, ByVal d, ByVal curix, ByVal comb)
Dim i As Long, comb2 As String

    For i = curix To n
        comb2 = comb & MyItems(i) & "|"
        If d + 1 = gs Then
            Results.Add comb2, 1
        Else
            Call Recur(n, gs, d + 1, i + 1, comb2)
        End If
    Next i

End Sub
 
Last edited:
Upvote 0
Thank you so much! That old post you mentioned, I tried adapting some old code from that project, but it worked a little differently and I couldn't get it to work.

Stepping through your code, I realize that I was getting close to to the answer, but not quite.

I'll study this and try to figure out how it works.

Thanks again, this has been driving me crazy.
 
Upvote 0

Forum statistics

Threads
1,221,310
Messages
6,159,176
Members
451,543
Latest member
cesymcox

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top