3

I've started a little side project to try to learn a few new concepts (hopefully in C++ or Python) and I was just hoping for a little help with the start of my idea.

*This is all related to a bigger fantasy basketball project, but I have to start somewhere.

I want to 100 variables (players) and find every combination of 10, that satisfies another condition.

For example; I have 100 players, and I want to find out how many combinations of 10 (no duplicates, and order does not matter (so ABC == CBA), will combine for a certain value (170 pts between the 10), or higher.

I assume there's a Python library to work this magic for me (which I would love to know about), but really, I'm more interested in how I would go about this using C++.

Thanks for any responses.

Mike Christensen
  • 88,082
  • 50
  • 208
  • 326
apichel
  • 91
  • 1
  • 1
  • 5
  • 3
    The problem I foresee here is that 100 choose 10 has 1.73103095 × 10e13 combinations. If you want any 10 players that satisfy a condition what I would recommend is sorting the players based on their value and choosing them based on that ranking. – twain249 Mar 07 '12 at 22:39
  • Wait, do you want to do this in Python or C++? You could do it without a library in Python too to actually learn the logic... – Silas Ray Mar 07 '12 at 22:40
  • Looping through all the combinations and testing is the wrong way to do this because it's O(n!) as @twain249 points out, this results in an impractical number of iterations. You will need to use dynamic programming to solve this in a time efficient manner – John La Rooy Mar 07 '12 at 22:45
  • 1
    I *think* this is a multiple knapsack problem if I'm reading correctly. I think it'll be extremely tough to find *all* combinations in linear time. There's algorithms that can estimate that sort of thing, perhaps look into simulated annealing. – Mike Christensen Mar 07 '12 at 22:49
  • If the values are bounded integers, then you can solve this efficiently using dynamic programming. – rettvest Mar 08 '12 at 07:08
  • Would it help to mention I want to run something along these lines for 9 separate categories. This has no practical purpose (other than hopefully teaching me something), and I figured fantasy basketball was a simple enough topic, (while giving me a somewhat complex problem I could work on.) So I want to find all combinations for the first category, and then see how many of those combinations work for the next category, etc. – apichel Mar 08 '12 at 20:08

3 Answers3

2

Here is some psuedo-code

function player_combos(array players, int minimum_total) {
  array result = []
  players = sort(players, metric=most points first)
  int total = 0
  for p1 in 0 .. length(players) {
    if players[p1].points*10 < minimum_total - total:
      break
    total += players[p1].points
    for p2 in p1+1 .. length(players) {
      if players[p2].points*9 < minimum_total - total:
        break
      total += players[p2].points
      for p3 in p2+1 .. length(players) {
        if players[p3].points*8 < minimum_total - total:
          break
        total += players[p3].points
        # continue these nested loops up to p10
        ...
                    for p10 in p9+1 .. length(players):
                      if players[p10].points < mininum_total - total:
                        break
                      # this is a valid combination
                      result.append((p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))
        ...
        # remember to decrement total when we finish a loop iteration
        total -= players[p3].points
      }
      total -= players[p2].points
    }
    total -= players[p1].points
  }
  return result
}

The idea here is that because you have the players sorted first, at any point while looping over players in the list, all players after must have an equal or lower point total as the current player. This allows you to break out of the current loop if the current player's points multiplied by the number of remaining spots left on the team is less than the number of points required to meet the minimum.

For example say you have four players on the team so far with 80 points total, that means you have 90 points left to reach the minimum, and there are 6 spots left. The absolute minimum number of points that your next player can have is 15 (since 90 / 6 == 15), so as soon as you reach a player in next loop that has 14 or fewer points, you can break out of that loop.

This should drastically reduce the total number of combinations you need to get, as long as your minimum_total metric is set high enough.

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • Going into this I knew this first step would result in a ridiculous number of combinations. The end goal here is to run something along these lines for 9 separate categories, outputting every 10 player grouping that meets every category requirement. – apichel Mar 08 '12 at 20:08
1

Sounds like a derivate of SUBSET SUM (having a fixed SUBSET size) problem, which is by the way proven to be NP-Complete. Maybe you can find help here: Optimizing subset sum implementation

Community
  • 1
  • 1
Simon
  • 9,255
  • 4
  • 37
  • 54
0

I would simply filter your list for all players withthe attributes you want and then loop over the filtered list for all of the combinations.

given your constraints you should be able to use a simple (if deep) nested loop.

tletnes
  • 1,958
  • 10
  • 30