Reputation: 73
I'm trying to produce an initial solution for the group balancing problem but I seem to be stuck on something that sounds like it should be quite simple.
Basically I have an array of weights (random integers), e.g.
W() = [1, 4, 3, 2, 5, 3, 2, 1]
And I want to create another array of the same length with the numbers 1 to the size of the array in place of the smallest to largest numbers respectively, e.g.
S() = [1, 7, 5, 3, 8, 6, 4, 2]
For duplicates, the first occurrence is taken as the smaller of the indices.
I originally used a BubbleSort algorithm, but unfortunately this does not allow me to give an output in the required format.
I understand that this is quite a specific problem, but any help would be greatly appreciated.
Upvotes: 5
Views: 400
Reputation: 73
Thank you so much for everyone who gave help!
I took your suggestions and somehow managed to forge my own solution, despite having spent an entire day working on something that has very little to do with my overall project.
Here is the following code I used:
Sub InitialSol(S() As Integer, n As Integer, k As Integer, W() As Long)
Dim i As Integer, c As Integer
Dim min As Long, max As Long, temp As Long
min = W(1)
max = W(1)
For i = 2 To n
If W(i) <= min Then
min = W(i)
End If
If W(i) >= max Then
max = W(i)
End If
Next i
c = 1
Do While c <= n
temp = max
For i = 1 To n
If W(i) = min Then
S(i) = c
c = c + 1
End If
Next i
For i = 1 To n
If W(i) > min And W(i) <= temp Then
temp = W(i)
End If
Next i
min = temp
Loop
End Sub
Upvotes: 0
Reputation: 9444
Give this a try and let me know how it works for you:
Option Base 0
Option Explicit
Option Compare Text
Sub tmpSO()
Dim tmp As Double
Dim strJoin As String
Dim i As Long, j As Long
Dim W As Variant, S() As Double, X() As Long
'Load W
W = Array(1, 4, 3, 2, 5, 3, 2, 1)
'Set the dimensions for the other arrays
ReDim S(LBound(W) To UBound(W))
ReDim X(LBound(W) To UBound(W))
'Copy W into S
For i = LBound(W) To UBound(W)
S(i) = W(i)
Next i
'Sort S
For i = LBound(S) To UBound(S) - 1
For j = i + 1 To UBound(S)
If S(i) > S(j) Then
tmp = S(j)
S(j) = S(i)
S(i) = tmp
End If
Next j
Next i
'Get the results into X
For i = LBound(S) To UBound(S)
X(i) = WorksheetFunction.Match(W(i), S, 0)
S(WorksheetFunction.Match(W(i), S, 0) - 1) = vbEmpty
Next i
'Print out W (original array)
Debug.Print Join(W, ",")
'Print out x (result array)
For i = LBound(X) To UBound(X)
strJoin = strJoin & "," & X(i)
Next i
Debug.Print mid(strJoin, 2)
End Sub
Upvotes: 2
Reputation: 29296
You have to find a way to glue together the values (content) and the indexes.
As you have flagged the with excel-vba
, I would suggest that you write you data into a sheet, first column the values and second column the indexes and sort them using range.sort
. After that, the 2nd column holds your order
If using Excel is not an option, the best bet I can think about is create a Scripting.Dictionary
(with index as key) and sort this (there is no build in function to sort it but googling it you can find some examples.
Or you could do something ugly like create a array of doubles from you data with the decimal part holding you index
[1.001, 4.002, 3.003, 2.004, 5.005, 3.006, 2.007, 1.008]
, sort this, get the decimals and multiply them back to integer.
Upvotes: 1