[Hard] Store Combinations in an array

Buzz1126

New Member
Joined
Jan 24, 2020
Messages
5
Office Version
  1. 2016
Platform
  1. Windows
Currently Working Program:
My program currently takes in a list of n players, and runs through each combination of m players (nCm), and pops out the combination with the most points, given the constraint that the cost must be less than the entered cost.

Normally this list could contain ~100 players but I want to keep it simple. For this example, we are choosing 3 players out of a possible 5 player pool and maximizing the total points (col. D) given that the total cost (col. C) is less than the max cost (cell C3).

Problem:
I would like to amend this program so that I can print the 5 combinations with the most total points (out of the 5C3 = 10 possible combinations).

Thank you in advance, and even help with the one of the steps to solve the problem would be use.

VBA Code:
Sub Run()
  Dim cTot          As Currency   ' number of combos
  Dim aiC()         As Long       ' combination
  Dim cComb         As Currency   ' combination counter
  Dim nCombLow      As Long       ' low bits of combin counter

  Dim tBeg          As Date       ' start date/time
  Dim tET           As Single     ' elapsed time
  Dim tETT          As Double     ' estimated total time
  Dim f             As Single     ' start time (seconds past midnight)

  Dim n             As Long       ' number of players
  Dim m             As Long       ' number to choose

  Dim i             As Long       ' scratch index
  Dim aiCost()      As Long       ' player cost
  Dim adPts()       As Double     ' player points
  Dim aiPick()      As Long       ' pick = 1
  Dim iTotCost      As Long       ' cost for a given combo
  Dim iMaxCost      As Long       ' max cost allowed
  Dim dTotPts       As Double     ' points for a given combo
  Dim dMaxPts       As Double     ' max points so far
 
  'print array work ********************************************
  Dim ResultsTab, CalculatorTab As Worksheet
  Set CalculatorTab = ThisWorkbook.Sheets("Calculator")
  Set ResultsTab = ThisWorkbook.Sheets("Results")
  Dim PrintArr(1 To 10, 1 To 6)   As Variant       ' array to be printed, nCm x m
    
  '*************************************************************
  m = Range("ptrChoose").Value2
  ReDim aiC(1 To m)
  aiC(1) = -1

  iMaxCost = Range("ptrMaxCost").Value2

  Range("ptrMsg").ClearContents

  With Range("tbl") 'clears contents and sorts the tbl
    .Columns(4).ClearContents
    .Sort Key1:=.Columns(3), Order1:=xlDescending, Header:=xlNo
    n = .Rows.Count
    ReDim aiCost(1 To n) 'redims the cost and points arrays
    ReDim adPts(1 To n)

    For i = 1 To n 'adds values to the cost and points arrays
      aiCost(i) = .Cells(i, 2).Value2
      adPts(i) = .Cells(i, 3).Value2
    Next i
  End With

  cTot = WorksheetFunction.Combin(n, m)
 
  tBeg = Now
  f = Timer

'***************************************************************
'***************************************************************
' While Combo
'

  Do While bNextCombo(aiC, n) 'do while aic() is not the last combo
    cComb = cComb + 1 'combination counter
    nCombLow = nCombLow + 1 'low bits of combination counter
    
'****************************************************************
'   for the timer
'****************************************************************
    If (nCombLow And &HFFFFFF) = 0 Then
      nCombLow = 0

      tET = (Timer - f) / 86400
      If tET < 0 Then tET = tET + 1
      tETT = tET * cTot / cComb
      Range("ptrMsg").Value = "  ET = " & Format(tET, "hh:mm:ss") & _
                              "  ETT = " & Format(tETT, "hh:mm:ss") & _
                              "  ETA = " & Format(tBeg + tETT, "ddd mmm dd hh:mm:ss")
    End If

'****************************************************************

'**** EVALUATE COMBO *******

    iTotCost = 0 'cost for a given combo
    dTotPts = 0 'points for a given combo
    
    'evaluates the cost and total pts of a given combination
    For i = 1 To m 'm is number of players in the combo
      iTotCost = iTotCost + aiCost(aiC(i) + 1) 'cost for a combination
      dTotPts = dTotPts + adPts(aiC(i) + 1) 'total points for a combination
    Next i
    
    'decides if current combo is max combo
    If iTotCost <= iMaxCost Then
      If dTotPts > dMaxPts Then
        dMaxPts = dTotPts
        ReDim aiPick(1 To n, 1 To 1)
        For i = 1 To m
          aiPick(aiC(i) + 1, 1) = 1
        Next i
        Range("tbl").Columns(4).Value = aiPick
        Beep
        DoEvents
      End If
    End If
  Loop
 End Sub
 
'***********************************************************************

 Public Function bNextCombo(aiC() As Long, n As Long) As Boolean
  ' shg 2009-12
  '     2011-07 (modified to require aiC(1) < 0 to initialize)

  ' VBA only

  ' Sets aiC to the next combination of n choose m in lexical order
  ' Returns True unless the combination is the last, in which case
  ' it leaves aiC unmodified.

  ' If aiC(1) < 0, initializes aiC to the first combo:
  '                   {m-1,  m-2, ...,     1,   0}
  ' The last combo is {n-1,  n-2, ..., n-m+1, n-m}

  Dim m             As Long
  Dim i             As Long

  m = UBound(aiC)
  If n < m Then Exit Function

' aic(1) = -1, therefore aic(1) = 1 if m=3
  If aiC(1) < 0 Then    ' set initial combo
    i = 1
    aiC(1) = m - 2

  Else

    ' find rightmost incrementable index
    For i = m To 2 Step -1
      If aiC(i) < aiC(i - 1) - 1 Then Exit For
    Next i
  End If

  If i <> 1 Or aiC(1) < n - 1 Then
    ' increment that index, and set 'righter' indices descending to 0
    aiC(i) = aiC(i) + 1
    For i = i + 1 To m
      aiC(i) = m - i
    Next i

    bNextCombo = True
  End If
End Function
 

Attachments

  • SetUp Pic.PNG
    SetUp Pic.PNG
    6.8 KB · Views: 19

Excel Facts

Control Word Wrap
Press Alt+Enter to move to a new row in a cell. Lets you control where the words wrap.
How many players do you need to choose in the complete problem?

J.Ty.
 
Upvote 0
in this example it would be 3 (5 total, choose), normally its nCm (where m is always 6)
 
Upvote 0
in this example it would be 3 (5 total, choose), normally its nCm (where m is always 6)
So, if you want to have 100 players and choose 6, you get
  • 1192052400 possible combinations
  • which is 6820.98 times more than the maximal number of rows in a single Excel workseheet
  • 7152314400 bytes of memory to store them, assuming 1 byte (equivalent of 1 alphanumeric character) per player, which is 6.661111861 GB
  • which requires 827.81 days to process, if you assume 1 ms per one choice.
It means it is rather infeasible to store that number of combinations in the memory of your computer, and you need an algorithm which is more clever than generating all combinations and cycling through them to choose the best one.

J.Ty.
 
Upvote 0
Right. Sorry I guess i wasn't clear. When i'm running for 100 players I will only print the top 10 or so combinations. The points are based on column d in the picture.

The first step in solving this problem I thought would be figuring out how to print all combinations. In this case 5c3 = 10 combinations. Then I would take the next step of storing the top 3 or so in an array, and print that.

I could send you this file if it would help?
 
Upvote 0
It doesn't matter how many combinations you want to store. It is still too time consuming to generate and consider them all, even if you do not want to keep them in memory.
Again, you need an algorithm which is more clever.

J.Ty.
 
Upvote 0
I understand, but am I wrong in how the program works now? It runs one combination at a time, and then if that combination has a total points greater than the previous combination it stores it in the aiPick() array. Why can't i just ammend the code to have, lets say 10 aipick() arrays to store the top 10 combinations with the most points?
 
Upvote 0
something like this

VBA Code:
Dim MaxValues(1 to 10)

For i = 1 to 10
    If testValue > MaxValues(i) Then
        For j = 9 to i Step - 1
            MaxValue(j+1) = MaxValue(j)
        Next j
        MaxValue(i) = testValue
        Exit For
    End If
Next i
 
Upvote 0
I understand, but am I wrong in how the program works now? It runs one combination at a time, and then if that combination has a total points greater than the previous combination it stores it in the aiPick() array. Why can't i just ammend the code to have, lets say 10 aipick() arrays to store the top 10 combinations with the most points?
You can do this, and this method will consider all possible 1192052400 combinations. If it takes only 1 millisecond per combination, you will wait over 2 years for the result. Even if it takes 0.1 millisecond per combination, it is still almost 3 months.

This is a situation when it is not enough to write some code, you need an algorithm.
 
Upvote 0
Hi

Maybe I'm not understanding but I don't think you have to get all combinations.

For ex.,
- you have 100 players and want the top ten combinations 6 at a time in terms of added points

In this case I'd just use the 8 players with more points and calculate their combinations. Combin(8,6) = 28
You'll just have to get the top ten out of these 28 combinations.

Remark: if the players may have the same number of points you may want to include more than 10 combinations, all those with at least the number of points of the 6th biggest sum.
 
Upvote 0

Forum statistics

Threads
1,215,357
Messages
6,124,482
Members
449,165
Latest member
ChipDude83

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