Highest Permutation Value

tazeo

Board Regular
Joined
Feb 15, 2007
Messages
133
Office Version
  1. 365
Platform
  1. Windows
I am think what I want to do is in the realms of the GURU excel user :) and well beyond what I can do.

This is for an online sports management game I play. Basically I have calculated each players skills in each position, and I need to find the best combination of the players on the field to give me the best team.

I have a table as below, and I need to find a solution that gives me what the best combination will be.
OTB1.xls
ABCDEFGHIJKLMNOPQRS
1NamePos1Pos2Pos3Pos4Pos5Pos5aPos6Pos7Pos8Pos8aPos9Pos9aPos10Pos11Pos12Pos12aPos13Pos13a
2Player149.20039.65044.80146.89056.33056.33063.90046.73554.80054.80049.17049.17056.48057.37064.00064.00052.50052.500
3Player250.06045.05054.67346.83055.74055.74069.13066.03560.10060.10066.26066.26054.72058.25057.40057.40054.40054.400
4Player348.13051.90060.35448.72048.87048.87056.90063.85550.20050.20066.81066.81049.48054.32048.30048.30058.40058.400
5Player446.52042.70049.30337.21038.32038.32044.72049.19541.10041.10051.71051.71035.84038.59037.20037.20042.40042.400
6Player559.96047.60056.18755.13067.97067.97077.65052.97060.80060.80064.84064.84057.02064.05065.30065.30064.50064.500
7Player646.07040.65039.95535.13028.63028.63036.40027.03525.90025.90037.64037.64024.04022.76027.60027.60041.60041.600
8Player763.13060.95065.75062.70060.06060.06062.72046.46551.80051.80059.83059.83045.73049.51053.60053.60058.00058.000
9Player859.17059.75067.93062.06064.18064.18070.21064.30561.30061.30070.22070.22059.84064.45063.90063.90065.50065.500
10Player947.46040.35051.76241.64049.89049.89058.90045.70046.50046.50058.32058.32022.98032.82029.00029.00033.30033.300
11Player1055.08055.10054.35057.00049.51049.51052.17040.09046.50046.50044.63044.63050.26045.84057.60057.60052.90052.900
12Player1169.71055.35058.53961.33067.57067.57080.05050.99562.70062.70061.69061.69062.04061.81072.80072.80069.00069.000
13Player1246.94042.10043.04143.05041.54041.54052.75038.88040.80040.80045.20045.20040.19038.07045.20045.20048.10048.100
14Player1359.03053.85063.98159.37065.96065.96071.71054.85561.60061.60064.45064.45044.88051.56054.00054.00047.30047.300
15Player1452.17049.60055.12050.68050.28050.28054.75045.40548.60048.60051.54051.54038.65040.51045.40045.40041.80041.800
16Player1561.45060.25065.97358.77054.88054.88062.36055.78555.90055.90061.50061.50042.29042.62049.10049.10046.80046.800
17Player1668.19063.20072.48262.18062.73062.73071.57061.13062.70062.70070.32070.32040.37044.42048.90048.90046.70046.700
18Player1751.36035.65043.34537.67051.00051.00069.55055.29555.40055.40058.56058.56047.59049.68052.90052.90049.90049.900
19Player1839.62031.30035.68631.54035.47035.47039.63028.80533.00033.00035.69035.69025.79028.57031.40031.40031.00031.000
20Player1963.40054.95059.91753.23053.88053.88064.98057.44559.10059.10058.81058.81048.40045.88056.00056.00047.60047.600
21Player2058.67053.55060.94057.18059.35059.35064.38046.61554.80054.80057.31057.31037.56041.89047.30047.30042.20042.200
Sheet2


Can anyone help?
 

Excel Facts

Can Excel fill bagel flavors?
You can teach Excel a new custom list. Type the list in cells, File, Options, Advanced, Edit Custom Lists, Import, OK
You'll need to tell us more about how the 'best' combination is to be determined - what happens, e.g., if the same player is best in 2 positions? & if the next best player is best in another position but the third placed player is so bad that it makes sense to use the second placed player & make do in the other position etc etc??

Is it always the case that the best team is the one with the highest possible scores?
 
Upvote 0
Okay I think this is what you asked:
A player can obviously only play in one position.
I want it so that the calculation works out the best combination of players. For example if you look at the scores for B2:D4 the best combination is actualy B2+C3+D4 even though it includes player 2's worst score.

With the same scores happening this will only happen with the #a positions (as the background calcs are complex) if that happens then they go into, say Pos 5, and the next selection goes into Pos 5a.

With 18 positions I would say that Yes it would be the best team has the highest score
 
Upvote 0
If it helps there are only 207 combinations

or should that be 1,216,451,004,088,320,000 - been a long day :-(
 
Upvote 0
Hi

I thought I would give this one a nudge.....but this only tests a very limited number of scenarios - nothing near the number you proposed. This routine starts at position 1, finds the best player for that position, then checks position 2 and so forth. Then it holds onto that result, and starts again but this time starting from position 2 and tries the whole thing again round to position 1 and so forth.

I haven't tried this the other way, where you select a player and find the best position and so on but that would be an interesting exercise (although somewhat harder given there are more players than positions). With a bit of modification you could make it loop backwards through the positions to see if it can find a better combination. All told, I think there are too many combinations to test so an approximation (as I have done) might have to do.

Anyway, copy this code into a standard VBA module and give it a go. Set the constant values at the top of the code with the top left cell reference of the score range. This will output the results onto whatever sheet you specify (in the code) starting at cell A1 - just use a blank sheet.

Good luck!

Andrew

Code:
Option Explicit

Public Sub FindBestCombo()

On Error GoTo EH

Const InputSheet As String = "Sheet1" 'change this to your input sheet name
Const OutputSheet As String = "Sheet2" 'change this to your output sheet name
Const StartRow As Long = "1" 'set this to the first row number (including the headings)
Const StartCol As Long = "1" 'set this to the first column number, e.g. "A" = 1, "B" = 2

Dim NumPlayers As Long, _
    NumPositions As Long, _
    NextPosition As Long, _
    tempVar As Long
Dim ScenarioLoop As Long, _
    PositionLoop As Long, _
    PlayerLoop As Long
Dim PlayerArray() As String, _
    PositionsArray() As String, _
    ScoreArray() As Double, _
    ResultsArray() As Long

NumPlayers = Sheets(InputSheet).Cells(StartRow, StartCol).End(xlDown).Row - 1
NumPositions = Sheets(InputSheet).Cells(StartRow, StartCol).End(xlToRight).Column - 1

ReDim PlayerArray(NumPlayers, 1) 'holds the players names and a used indicator
ReDim PositionsArray(NumPositions) 'holds the position names
ReDim ResultsArray(NumPositions, 1) 'holds the player number for each position
'ResultsArray : 2nd dimension 0 = best, 1 = challenger
ReDim ScoreArray(NumPlayers, NumPositions) 'holds the scores

'Import the names, positions & scores
'Initialise the arrays
With Sheets(InputSheet)
    For PlayerLoop = 1 To NumPlayers
        PlayerArray(PlayerLoop, 0) = .Cells(StartRow + PlayerLoop, StartCol).Value
        PlayerArray(PlayerLoop, 1) = 0 'not used indicator
        For PositionLoop = 1 To NumPositions
            ScoreArray(PlayerLoop, PositionLoop) = .Cells(StartRow + PlayerLoop, StartCol + PositionLoop).Value
        Next PositionLoop
    Next PlayerLoop
    For PositionLoop = 1 To NumPositions
        PositionsArray(PositionLoop) = .Cells(StartRow, StartCol + PositionLoop).Value
    Next PositionLoop
End With

For ScenarioLoop = 1 To NumPositions
    For tempVar = 1 To NumPositions
        ResultsArray(tempVar, 1) = 0 'clear the results array
    Next tempVar
    For PlayerLoop = 1 To NumPlayers
        PlayerArray(PlayerLoop, 1) = 0 'set all players to not used
    Next PlayerLoop
    For PositionLoop = ScenarioLoop To (ScenarioLoop + NumPositions - 1)
        If PositionLoop > NumPositions Then
            tempVar = PositionLoop - NumPositions
        Else
            tempVar = PositionLoop
        End If
        For PlayerLoop = 1 To NumPlayers
            If PlayerArray(PlayerLoop, 1) = 0 Then 'not used yet
                If ResultsArray(tempVar, 1) = 0 Then 'first free player
                    ResultsArray(tempVar, 1) = PlayerLoop
                    PlayerArray(PlayerLoop, 1) = 1
                Else
                    If ScoreArray(PlayerLoop, tempVar) > ScoreArray(ResultsArray(tempVar, 1), tempVar) Then
                        'better score
                        PlayerArray(ResultsArray(tempVar, 1), 1) = 0
                        PlayerArray(PlayerLoop, 1) = 1
                        ResultsArray(tempVar, 1) = PlayerLoop
                    ElseIf ScoreArray(PlayerLoop, tempVar) = ScoreArray(ResultsArray(tempVar, 1), tempVar) Then
                        'same score
                        If tempVar = NumPositions Then
                            NextPosition = 1
                        Else
                            NextPosition = tempVar + 1
                        End If
                        'Check the next position value
                        If ScoreArray(PlayerLoop, NextPosition) < ScoreArray(ResultsArray(tempVar, 1), NextPosition) Then
                            PlayerArray(ResultsArray(tempVar, 1), 1) = 0
                            PlayerArray(PlayerLoop, 1) = 1
                            ResultsArray(tempVar, 1) = PlayerLoop
                        End If
                    End If
                End If
            End If
        Next PlayerLoop
    Next PositionLoop
    If ScenarioLoop = 1 Then
        'Store this combination as the best
        For PositionLoop = 1 To NumPositions
            ResultsArray(PositionLoop, 0) = ResultsArray(PositionLoop, 1)
        Next PositionLoop
        ResultsArray(0, 0) = 0 'calculate total
        For PositionLoop = 1 To NumPositions
            ResultsArray(0, 0) = ResultsArray(0, 0) + ScoreArray(ResultsArray(PositionLoop, 0), PositionLoop)
        Next PositionLoop
    Else
        'Check the new combination versus the current best
        ResultsArray(0, 1) = 0
        For PositionLoop = 1 To NumPositions
            ResultsArray(0, 1) = ResultsArray(0, 1) + ScoreArray(ResultsArray(PositionLoop, 1), PositionLoop)
        Next PositionLoop
        If ResultsArray(0, 1) > ResultsArray(0, 0) Then
            'Found a better combination
            For PositionLoop = 1 To NumPositions
                ResultsArray(PositionLoop, 0) = ResultsArray(PositionLoop, 1)
            Next PositionLoop
            ResultsArray(0, 0) = ResultsArray(0, 1) 
        End If
    End If
Next ScenarioLoop

'Show the results
With Sheets(OutputSheet)
    For PositionLoop = 1 To NumPositions
        .Cells(PositionLoop, 1) = PositionsArray(PositionLoop)
        .Cells(PositionLoop, 2) = PlayerArray(ResultsArray(PositionLoop, 0), 0)
        .Cells(PositionLoop, 3) = ScoreArray(ResultsArray(PositionLoop, 0), PositionLoop)
    Next PositionLoop
    .Cells(NumPositions + 1, 1) = "Total"
    .Cells(NumPositions + 1, 3) = ResultsArray(0, 0)
End With

MsgBox "Finished!", vbInformation, "Done"

Exit Sub

EH:
    MsgBox Err.Description, vbCritical, "Error# " & Err.Number

End Sub

{late edit : fixed bug}
 
Upvote 0
Hi,

Exceptionally I'll post code while I'm not sure at all anymore if this is correct. I'm sure it can generate the correct result, but the way to get there seems sooo loooong.

there are 18 columns with Positions & 20 Players
so that makes permutations of 18 out of 20
isn't that 1.200.000.000.000.000.000 possibilities?

suppose 5 rows 2 columns
you can generate all permutations
A 1, 2
B 1, 3
...
C 2, 1

and sum the values (cell relative to the range)
A = cell(1, 1) + cells(2, 2)
B= cell(1, 1) + cells(3/b], 2)
C= cell(2/b], 1) + cells(1/b], 2)

doesn't this prove that you need all permutations?

Code:
Option Explicit

Dim indexes As Variant
Dim Results As Worksheet
Dim maxComb As Variant
Dim maxVal As Long
Dim arr As Variant
Dim l As Long
Dim loops As Variant
Dim starttime As Double


'
' Myrna Larson,  July 25, 2000,  Microsoft.Public.Excel.Misc

Sub ListPermutationsOrCombinations()
Dim Rng As Range
Dim m As Long
Dim n As Long 'Double

'Application.EnableCancelKey = xlErrorHandler
'On Error GoTo skip


maxVal = 0
l = 0
Set Rng = Sheets(2).Range("B2:K21") 'Range("B2:S21")

arr = Rng.Value
n = UBound(arr, 1)  'Number of items
m = UBound(arr, 2)  'Items taken at a time


Set Results = Sheets(3)
Results.Columns("A:B").Clear

ReDim indexes(1 To n)
Dim i As Long
    For i = 1 To n
    indexes(i) = i
    Next i

loops = Application.WorksheetFunction.Permut(n, m)

    If loops > 10 ^ 7 Then
    MsgBox "Long process. Watch statusbar" & vbLf & _
    "Press Esc to stop. Current best will be displayed.", 64, "INFO"
    End If

starttime = Time
AddPermutation n, m

skip:
Application.StatusBar = False

    With Rng
    .Interior.ColorIndex = xlNone
        For i = 1 To m
        Rng(maxComb(i), i).Interior.ColorIndex = 6
        Next i
    End With


MsgBox "Max = " & maxVal, 64, "REPORT"

End Sub

Private Sub AddPermutation(Optional n As Long = 0, _
Optional m As Long = 0, _
Optional NextMember As Long = 0)

Static iPopSize As Long
Static iSetSize As Long
Static SetMembers() As Long
Static Used() As Long
Dim i As Long

    If n <> 0 Then
    iPopSize = n
    iSetSize = m
    ReDim SetMembers(1 To iSetSize) As Long
    ReDim Used(1 To iPopSize) As Long
    NextMember = 1
    End If

    For i = 1 To iPopSize
        If Used(i) = 0 Then
        SetMembers(NextMember) = i
            If NextMember <> iSetSize Then
            Used(i) = True
            AddPermutation , , NextMember + 1
            Used(i) = False
            Else
            operate SetMembers()
            End If
        End If

    Next i

    If NextMember = 1 Then
    Erase SetMembers
    Erase Used
    End If

End Sub


Private Sub operate(ItemsChosen() As Long)
Dim i As Long
Dim CombSum As Long
Dim sValue As String
Dim cntLoops As String
Dim endtime As String

    For i = 1 To UBound(ItemsChosen)
    CombSum = CombSum + arr(ItemsChosen(i), i)
    Next i

    If CombSum > maxVal Then
    maxVal = CombSum
    maxComb = ItemsChosen
    End If

    l = l + 1
    If l Mod 333333 = 0 Then
    cntLoops = "Done: " & Format(Round(l / loops, 4), "0.00%")
    'end time ??? perhaps not correct ... or does it really take ages ???
    'endtime = " Endresult " & Format(Now + (Time - starttime) / l * loops, "\Date: MMDDYYYY \Hour: HH:MM AM/PM")
    Application.StatusBar = cntLoops & " Current Maximum " & maxVal & endtime
    End If
        
End Sub
kind regards,
Erik
 
Upvote 0
@Andrew
That works well and I can even see how it works :) Although it doesn't exhaust all the permutations, it is certainly better than the mark one eyeball method I have been using :lol:

@Erik
I'm not sure how to get this going, I reckognise that a simple cut and past won't work, but thats about as far as my experience gets :-(

And thanks to you both
 
Upvote 0
Hi

I fixed a bug in the code earlier today so you may want to check you have the correct version. Did you get 1073.8?

Given the number of permutations (and Erik's experiences with the long loops) I purposely didn't try to test all of the possible combinations. I simply coded a method a person might use when trying to manually solve the problem.

As far as I can see this thread is a long way from being resolved - I believe an alternative solution is being played with as we post.....but we will wait and see what develops.

Andrew
 
Upvote 0
Hi Andrew
Yep I used you updated code and it works as you have explained.

Again thanks to both you and Erik, and whom ever may be working in the wings... :wink:
 
Upvote 0

Forum statistics

Threads
1,223,246
Messages
6,170,988
Members
452,373
Latest member
TimReeks

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top