johnbeatty02
johnbeatty02

Reputation: 83

Team Making using Python?

I am running a tournament for 16 people, and each tournament, every person earns a certain number of points. These points are earned from 8 different games.

I need to make four teams of four, and their averages and standard deviations should ideally be as close together as possible (to make the fairest teams). I have already done this using a binpacking library. However, I have read that the knapsack problem is often better than binpacking at picking teams.

Ideally, I would be able to select one of the 8 games to balance points off of and obtain fair teams from that; right now I am just using overall points.

If anybody knows of any libraries or functions I can borrow to complete this task, please let me know. Additionally, if there are ways I can further optimize my code, please tell– I am still a beginner. My code is below.

import numpy as np

levels = np.genfromtxt('points.txt', dtype = 'float')
players = np.genfromtxt('players.txt', dtype = 'str')
playerLevels = zip(players, levels)
playerLevelsList = list(playerLevels)

averageLevels = sum(levels)/len(levels)
print('Average points are', averageLevels)

bins = binpacking.to_constant_bin_number(playerLevelsList, 4, 1)

a, b, c, d = [ [individualArray] for individualArray in bins]

a = a[0]
b = b[0]
c = c[0]
d = d[0]
a1 = a[1]
b1 = b[1]
c1 = c[1]
d1 = d[1]

team1 = list(zip(*a))
team2 = list(zip(*b))
team3 = list(zip(*c))
team4 = list(zip(*d))

points1 = sum(team1[1])/4
points2 = sum(team2[1])/4
points3 = sum(team3[1])/4
points4 = sum(team4[1])/4

stdev1 = np.std(team1[1])
stdev2 = np.std(team2[1])
stdev3 = np.std(team3[1])
stdev4 = np.std(team4[1])

print('Team 1 is', team1[0])
print('Team 2 is', team2[0])
print('Team 3 is', team3[0])
print('Team 4 is', team4[0])
print('\n-----Stats-----')
print('Team 1 Average is', points1, 'with a standard deviation of', stdev1)
print('Team 2 Average is', points2, 'with a standard deviation of', stdev2)
print('Team 3 Average is', points3, 'with a standard deviation of', stdev3)
print('Team 4 Average is', points4, 'with a standard deviation of', stdev4)```

Upvotes: 1

Views: 428

Answers (1)

David Filler
David Filler

Reputation: 196

This may be a start to your answer. This was interesting and I had some time to kill. I was curious just how many unique team combinations are possible. Using an online combinations and permutations calculator I found out there are only 1820 unique teams possible when selecting 4 from 16 when order is not important. Using Python I generated a list of possible unique teams.

import matplotlib.pyplot as plt
import itertools as it

team_score_total=[]

teams = []
players=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]

for i in it.combinations(players, 4):
    teams.append(list(i))

# only 1,820 unique team possibilities
print(len(teams))

#check if there are duplicate players before adding to league
def CanAddTeamLeague(team, league):
    for t in league:
        for i in t:
            if i in team:
                return False
    return True;

#check if there are duplicate leagues before adding to list
def CanAddLeagueToList(league, league_list):
    for lg_list in league_list:
        count=0
        for t1 in lg_list:
            for t2 in league:
                if t1 == t2:
                    count+=1
                    if count ==4:
                        return False
    return True;            

unique_league_list = []
for i in range(len(teams)):
    league = []
    league.append(teams[i])
    for t in teams:
        if CanAddTeamLeague(t,league):
            if len(league) < 4:
                league.append(t)
        if len(league) == 4:
            if CanAddLeagueToList(league,unique_league_list):
                unique_league_list.append(league)

print(len(unique_league_list))
for l in unique_league_list:
    print(l)

# for i in teams:
#     print(i)
    
# for t in teams:
#     team_score_total.append(scores[t[0]]+scores[t[1]]+scores[t[2]]+scores[t[3]])

# fig, ax = plt.subplots(figsize=(20, 12))
# plt.plot(range(len(teams)),team_score_total)

This got me to wondering just how many truly unique leagues of 4 teams are possible. I think the answer is 1715. I switched to Java to figure this out and it took 24 seconds on my machine for the code to eliminate duplicate possibilities. I don't think I have the math skills to calculate that with combinations/permutations (but somebody does). Having said that, 1715 is not a huge number to deal with for brute force methods and I don't think it would take much time to calculate the stats for each team.

Here is the final piece. I put this in another cell so you don't have to recalculate the time consuming part every time.

import numpy as np
scores=[7,11,20,21,22,12,13,14,15,16,23,18,19,17,24,10]

league_score_list = []
for league in unique_league_list:
    league_score=[]

    for team in league:
        team_score=0
        for ts in range(4):
            team_score += scores[team[ts]]
        league_score.append(team_score)
    league_score_list.append(league_score)            

std_list=[]
for l in league_score_list:
    std_list.append(np.std(l))

sorted_list = np.argsort(std_list)
print(league_score_list[sorted_list[0]])
print(unique_league_list[sorted_list[0]])

Upvotes: 1

Related Questions