4

I need an algorithm which generates all possible combination of a set number and output all of them onto Excel spreadsheet.

For example, with n = 5(1,2,3,4,5) and r = 2(created a small gui for this), it will generate all possible combinations and output them into excel spreadsheet like this...

1,2
1,3
1,4
...

The order in which it prints doesn't matter. It can first print (5,1), then (1,2). Can anyone show me how to do this?

Thank you very much.

9
  • 2
    Is order important? Is 5,1 the same as 1,5 ? Commented Aug 25, 2011 at 23:29
  • 1
    If order (as Tim asked it) is important, then "all possible combinations" can grow quickly. If n and r are both 8, that's factorial 8, or over 40,000 permutations. Do you have a limit for n in mind? Commented Aug 26, 2011 at 0:18
  • 1
    Yes the order is important. Sorry for not putting that in. 1,5 is same as 5,1. Commented Aug 26, 2011 at 0:42
  • 1
    No I don't have limits for n or r. I want to make it dynamic so any user can put in any number and it will generate the spreadsheet with all possible combinations. Commented Aug 26, 2011 at 0:50
  • 3
    Can't believe nobody has asked this one yet: Have you tried anything yourself? The answer is basically two nested For Next loops. Commented Aug 26, 2011 at 7:07

4 Answers 4

8

How about this code...

Option Explicit

Private c As Integer

Sub test_print_nCr()
  print_nCr 5, 3, Range("A1")
End Sub

Function print_nCr(n As Integer, r As Integer, p As Range)
  c = 1
  internal_print_nCr n, r, p, 1, 1
End Function


Private Function internal_print_nCr(n As Integer, r As Integer, ByVal p As Range, Optional i As Integer, Optional l As Integer) As Integer

  ' n is the number of items we are choosing from
  ' r is the number of items to choose
  ' p is the upper corner of the output range
  ' i is the minimum item we are allowed to pick
  ' l is how many levels we are in to the choosing
  ' c is the complete set we are working on

  If n < 1 Or r > n Or r < 0 Then Err.Raise 1
  If i < 1 Then i = 1
  If l < 1 Then l = 1
  If c < 1 Then c = 1
  If r = 0 then 
    p = 1
    Exit Function
  End If

  Dim x As Integer
  Dim y As Integer

  For x = i To n - r + 1
    If r = 1 Then
      If c > 1 Then
        For y = 0 To l - 2
          If p.Offset(c - 1, y) = "" Then p.Offset(c - 1, y) = p.Offset(c - 2, y)
        Next
      End If
      p.Offset(c - 1, l - 1) = x
      c = c + 1
    Else
      p.Offset(c - 1, l - 1) = x
      internal_print_nCr n, r - 1, p, x + 1, l + 1
    End If
  Next

End Function
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! Now I just need to figure out how to print them on one cells each. I'm new to VBA so I've been learning it for past 2 days.
8

I had to do this once and ended up adapting this algorithm. It's somewhat different from nested loops, so you may find it interesting. Translated to VB, this would be something like this:

Public Sub printCombinations(ByRef pool() As Integer, ByVal r As Integer)
    Dim n As Integer
    n = UBound(pool) - LBound(pool) + 1

   ' Please do add error handling for when r>n

    Dim idx() As Integer
    ReDim idx(1 To r)
    For i = 1 To r
        idx(i) = i
    Next i

    Do
        'Write current combination
        For j = 1 To r
            Debug.Print pool(idx(j));
            'or whatever you want to do with the numbers
        Next j
        Debug.Print

        ' Locate last non-max index
        i = r
        While (idx(i) = n - r + i)
            i = i - 1
            If i = 0 Then
                'All indexes have reached their max, so we're done
                Exit Sub
            End If
        Wend

        'Increase it and populate the following indexes accordingly
        idx(i) = idx(i) + 1
        For j = i + 1 To r
            idx(j) = idx(i) + j - i
        Next j
    Loop
End Sub

3 Comments

Thank you. I tried it and it works fine but array input in Excel spreadsheet wasn't what I was looking for. But I tried it and it works perfectly for anyone else who might need this.
That's why I say "something like" :-)
@Joubarc Is it going to work for something like this: array(2,3,4,5,7,10),where r=3?
1

These combination algorithms are best made with nested loops with recursion. I have wrote some 4 years ago the exactly needed code to carry this out (https://vitoshacademy.com/vba-nested-loops-with-recursion). The idea is to change the size variable in the Main and the input array in the same Sub. Then run it:

Sub Main()

    Static size         As Long
    Static c            As Variant
    Static arr          As Variant
    Static n            As Long

    size = 2
    c = Array(1, 2, 3, 4, 5, 6)

    n = UBound(c) + 1
    ReDim arr(size - 1)

    EmbeddedLoops 0, size, c, n, arr

End Sub

Function EmbeddedLoops(index, k, c, n, arr)

    Dim i                   As Variant

    If index >= k Then
        PrintArrayOnSingleLine arr
    Else
        For Each i In c
            arr(index) = i
            EmbeddedLoops index + 1, k, c, n, arr
        Next i
    End If

End Function

The debug.print has built-in limit in VBA, displaying only the last 200 values in the Immediate Window (Ctrl+G). Thus, if you have more than 200 lines of results, it is better to write to Excel spreadsheet, to a txt.file or to a database:

Public Sub PrintArrayOnSingleLine(myArray As Variant)

    Dim counter     As Integer
    Dim textArray     As String

    For counter = LBound(myArray) To UBound(myArray)
        textArray = textArray & myArray(counter)
    Next counter

    Debug.Print textArray

End Sub

Comments

0

This is my solution with arrays vba

Private Sub UserForm_Initialize()

Dim matriz_origen() As Variant

Dim matriz_destino() As Variant

Dim n As Long

Dim k As Long

n = 6

k = 2

Call combinatoria(matriz_origen, matriz_destino, n, k)

'Def titulo

Title = "Matriz Combinatoria"

'FUnction Calling

Call despliegue_2D(matriz_destino, Style, Title)

End Sub


Function combinatoria(matriz() As Variant, comb As Long, _
                      matriz_origen() As Variant, matriz_destino() As Variant, _
                      n As Long, k As Long)

'This function is calculating all possible combinations.

comb = Application.WorksheetFunction.Combin(n, k) 'Sin repeticion

ReDim matriz_origen(1 To n, 1 To k)

'Loops

For j = 1 To k

     For i = 1 To n

         matriz_origen(i, j) = i

     Next i

Next j

ReDim matriz_destino(1 To comb, 1 To k) 'comb

If (k = 2) Then

cont1 = 1

'Loops

For j = 1 To k - 1

pos1 = j + 1

For i = 1 To n

For iter1 = 1 To n

 If matriz_origen(i, j) < matriz_origen(iter1, pos1) Then

    matriz_destino(cont1, j) = matriz_origen(i, j)

    matriz_destino(cont1, pos1) = matriz_origen(iter1, j)

    cont1 = cont1 + 1

 End If

Next iter1

Next i

Next j

End If

If (k = 3) Then

cont1 = 1

'Loops

For j = 1 To k - 2

pos1 = j + 1

pos2 = j + 2

For i = 1 To n

For iter1 = 1 To n

 If matriz_origen(i, j) < matriz_origen(iter1, pos1) Then

  For iter2 = 1 To n

   If matriz_origen(iter1, pos1) < matriz_origen(iter2, pos2) Then

    matriz_destino(cont1, j) = matriz_origen(i, j)

    matriz_destino(cont1, pos1) = matriz_origen(iter1, j)

    matriz_destino(cont1, pos2) = matriz_origen(iter2, j)

    cont1 = cont1 + 1

   End If

 Next iter2

 End If

Next iter1

Next i

Next j

End If

If (k = 4) Then

cont1 = 1

'Loops

For j = 1 To k - 3

pos1 = j + 1

pos2 = j + 2

pos3 = j + 3

For i = 1 To n

For iter1 = 1 To n

 If matriz_origen(i, j) < matriz_origen(iter1, pos1) Then

  For iter2 = 1 To n

  If matriz_origen(iter1, pos1) < matriz_origen(iter2, pos2) Then

    For iter3 = 1 To n

      If matriz_origen(iter2, j) < matriz_origen(iter3, pos1) Then

       matriz_destino(cont1, j) = matriz_origen(i, j)

       matriz_destino(cont1, pos1) = matriz_origen(iter1, j)

       matriz_destino(cont1, pos2) = matriz_origen(iter2, j)

       matriz_destino(cont1, pos3) = matriz_origen(iter3, j)

       cont1 = cont1 + 1

       End If

    Next iter3

   End If

 Next iter2

 End If

Next iter1

Next i

Next j

End If

End Function


Function despliegue_2D(matriz() As Variant, Style As String, Title As String)

'Esta funcion permite el despliegue de un arreglo multidimentinal de 2 dimensiones.

'Declaration

Dim msg As String

Dim iter1 As Integer, iter2 As Integer

'Declaration

filas = UBound(matriz, 1)

columnas = UBound(matriz, 2)

'Loops

For iter1 = 1 To filas

    For iter2 = 1 To columnas

        msg = msg & matriz(iter1, iter2) & vbTab

    Next iter2

    msg = msg & vbCrLf

Next iter1

Response = MsgBox(msg, Style, Title)

End Function

3 Comments

finally join the arrays
Welcome to SO! When you post a reply, try to check that it is an answer to the original question. In your case, we cannot knot if it is, as part of your code is calling procedures that are not expose as despliegue_1D. You are fixing the number of items, that is variable... Edit your reply and complete your code.
Thank you for your comments, i will complete my code with additional functions and ,matrices.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.