Yesterday I received an email, refering to some 2 old articles in VitoshAcademy for nested loops without recursion:
As far as the person from the email was taking a look at the code and was struggling, wanting to perform the combinations of the set [1,2,3,4,5,6] with 4 samples, I thought it would be interesting, if I give it a try, rewriting the old code I was using almost 5 years ago.
It was fun to see how I was thinking about programming back then and that I actually have changed slightly after. Anyway, while rewriting the code I noticed, that there are 2 main differences between permutations and combinations:
- In combinations there are no values repeated;
- In combinations every value is bigger than the previous one;
The latter is actually not true in general, but if we follow this rule, we are forced to skip adding “1243” after having already written “1234”. So, it is a kind of logic I decided to use, as far as sorting and implementing to a set was requiring more words to explain.
Long story short, implementing the old code I wrote 5 years ago, I have added 2 new conditions:
1 2 |
If Not AnyValueBiggerThanNext(arr) And Not AnyValueIsRepeated(arr) Then PrintArrayOnSingleLine arr |
And it actually brought me to the desired result:
And this is the code, which probably looks better than the one I have written in 2015:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
Sub Main() Dim size As Long: size = 4 Dim initialArray As Variant: initialArray = Array(1, 2, 3, 4, 5, 6) Dim arr As Variant: ReDim arr(size - 1) Dim n As Long: n = UBound(arr) + 1 EmbeddedLoops 0, size, initialArray, n, arr End Sub Function EmbeddedLoops(index As Long, size As Long, initialArray As Variant, n As Long, arr As Variant) Dim p As Variant If index >= size Then If Not AnyValueBiggerThanNext(arr) And Not AnyValueIsRepeated(arr) Then PrintArrayOnSingleLine arr End If Else For Each p In initialArray arr(index) = p EmbeddedLoops index + 1, size, initialArray, n, arr Next p End If End Function Public Function AnyValueBiggerThanNext(arr As Variant) As Boolean Dim i As Long For i = LBound(arr) To UBound(arr) - 1 If arr(i) > arr(i + 1) Then AnyValueBiggerThanNext = True Exit Function End If Next i AnyValueBiggerThanNext = False End Function Public Function AnyValueIsRepeated(arr As Variant) As Boolean On Error GoTo AnyValueIsRepeated_Error: Dim element As Variant Dim testCollection As New Collection For Each element In arr testCollection.Add "item", CStr(element) Next element AnyValueIsRepeated = False On Error GoTo 0 Exit Function AnyValueIsRepeated_Error: AnyValueIsRepeated = True End Function Public Sub PrintArrayOnSingleLine(myArray As Variant) Dim i As Long Dim textArray As String For i = LBound(myArray) To UBound(myArray) textArray = textArray & myArray(i) Next i Debug.Print textArray End Sub |
Actually, there are plenty of faster ways to make it happen, but my idea was to rewrite the old code with some new conditions. A quick good look for the faster ways – https://stackoverflow.com/questions/127704/algorithm-to-return-all-combinations-of-k-elements-from-n
Hope you are enjoying it. 🙂