Oliver Jack Baynham
Oliver Jack Baynham

Reputation: 73

Indices of elements in order from smallest to largest

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

Answers (3)

Oliver Jack Baynham
Oliver Jack Baynham

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

Ralph
Ralph

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

FunThomas
FunThomas

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

Related Questions