Vba subset summation algorithm
I am trying to write an algorithm to solve the subset sum problem.
I believe I have the beginning of an algorithm, but I want to write something that will start with 1 set of N sets depending on the length of the array. Ideally this will spill out the first result that matches.
I believe it could be better written as it follows the pattern.
Any input is greatly appreciated.
Thank!
Antonio
Function SubnetSum()
Dim num() As Variant
Dim goal As Double
Dim result As Double
Num() = array (1,2,3,4,5,6,7,8,9,10)
goal = 45
For i = LBound(num) To UBound(num)
If num(i) = goal Then
MsgBox num(i) & " " & goal & " 1 Set"
Exit Function
End If
Next
For i = LBound(num) To UBound(num)
For j = i + 1 To UBound(num)
If num(i) + num(j) = goal Then
result = num(i) + num(j)
MsgBox result & " " & goal & " 2 Sets"
Exit Function
End If
Next
Next
For i = LBound(num) To UBound(num)
For j = i + 1 To UBound(num)
For k = j + 1 To UBound(num)
If num(i) + num(j) + num(k) = goal Then
result = num(i) + num(j) + num(k)
MsgBox result & " " & goal & " 3 Sets"
Exit Function
End If
Next
Next
Next
For i = LBound(num) To UBound(num)
For j = i + 1 To UBound(num)
For k = j + 1 To UBound(num)
For l = k + 1 To UBound(num)
If num(i) + num(j) + num(k) + num(l) = goal Then
result = num(i) + num(j) + num(k) + num(l)
MsgBox result & " " & goal & " 4 Sets"
Exit Function
End If
Next
Next
Next
Next
For i = LBound(num) To UBound(num)
For j = i + 1 To UBound(num)
For k = j + 1 To UBound(num)
For l = k + 1 To UBound(num)
For m = l + 1 To UBound(num)
If num(i) + num(j) + num(k) + num(l) + num(m) = goal Then
result = num(i) + num(j) + num(k) + num(l) + num(m)
MsgBox result & " " & goal & " 5 Sets"
Exit Function
End If
Next
Next
Next
Next
Next
MsgBox "Nothing found"
End Function
Edit
@Enderland Thanks for the article, I found it quite amusing and sorry as this is my first post on this site.
What I am trying to do is solve the subset sum problem, that is, I have a goal of 9 and using a set of numbers [1,2,3,4,5], I want to find the most optimal way to go to 5 using the combination numbers in the array.
Possible solutions are [5], [5.4], [5,3,1], [4,3,2]. However, I want to get the most optimal solution, which is [5].
Also, if my goal is to get 14 from [1,2,3,4,5], it will loop through all possible combinations of additions in the array of numbers and splash out the most optimal solution, which in this case [5,4,3, 2].
What my code does is that it pushes the array numbers down to 5 values ββuntil it gets the most optimal solution.
What I want to do is write a recursive loop so that it is not hardcoded for only 5 possible values. Instead, I want to be able to loop through a combination of numbers with N possible values ββbased on the size of the array.
However, I cannot think of a loop that would support this feature. I'm sure this is possible with a little recursion.
I guess my question would be ... Is there a way to solidify the code I have above into one complex recursive function?
Thank!
source to share
I needed a similar recursive function. Here is the code.
* add your own error handling
Public Function fSubSet(arr As Variant, goal As Double, Optional arrIndices As Variant) As Boolean
Dim i As Integer
Dim intSumSoFar As Integer
i = 0
If IsMissing(arrIndices) Then
arrIndices = Array(0)
End If
For i = LBound(arrIndices) To UBound(arrIndices)
intSumSoFar = intSumSoFar + arr(arrIndices(i))
Next
If intSumSoFar = goal Then
For i = LBound(arrIndices) To UBound(arrIndices)
Debug.Print arr(arrIndices(i))
Next
fSubSet = True
Exit Function
End If
'now we increment one piece of the array starting from the last one
i = UBound(arrIndices)
Do While i > -1
If arrIndices(i) + (UBound(arrIndices) - i) < UBound(arr) Then
arrIndices(i) = arrIndices(i) + 1
Exit Do
End If
i = i - 1
Loop
'if we are on the first index of the indices array and it is pushed as far as it can go then reset the array and add one to it if that doesn't make it too big
If i = -1 And UBound(arrIndices) < UBound(arr) Then
ReDim arrIndices(UBound(arrIndices) + 1)
For i = 0 To UBound(arrIndices)
arrIndices(i) = i
Next
'we need to end this monster
ElseIf i = -1 And UBound(arrIndices) = UBound(arr) Then
fSubSet = False
Exit Function
End If
fSubSet = fSubSet(arr, goal, arrIndices)
End Function
Public Function fTestSubSet()
Debug.Print fSubSet(Array(1, 2, 5, 6, 11, 10), 35)
End Function
source to share