Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 403
Oliver Jack Baynham Avatar asked Oct 17 '22 14:10

Oliver Jack Baynham


2 Answers

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
like image 121
Ralph Avatar answered Nov 15 '22 07:11

Ralph


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.

like image 23
FunThomas Avatar answered Nov 15 '22 06:11

FunThomas