Skip to content

Instantly share code, notes, and snippets.

@andrewpatt24
Last active August 29, 2015 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewpatt24/e41a2b345405ced27280 to your computer and use it in GitHub Desktop.
Save andrewpatt24/e41a2b345405ced27280 to your computer and use it in GitHub Desktop.
"Dota 2 Game Prediction" submission to Hackerrank - 2nd in UK! (Code posted to Hackerrank is only bottom portion)
##########################################################################################################
## All below code is just calculation for each player type in game and there ELO from the training data ##
##########################################################################################################
################################################################
## General ELO rating functions ################################
################################################################
def expected_score(own_rating,opp_rating):
return 1.0/(1.0+10.0**((float(opp_rating)-float(own_rating))/400.0))
def adjustment(expected,actual,k=10.0):
return k*(actual-expected)
def actual_score(own_result,opp_result):
if own_result == opp_result:
return 0.5
else:
return own_result
################################################################
## function to calcualte newelo of a given player in array #####
################################################################
def new_player_elo(i,elos,results,k=10.0):
expected_array = [expected_score(elos[i],x) for x in elos]
actual_array = [actual_score(results[i],j) for j in results]
adjustment_array = [adjustment(e,a,k) for e,a in zip(expected_array,actual_array)]
return float(elos[i]) + sum(adjustment_array)
############################################################
## function to loop over above and get array of new ELOs ###
############################################################
def new_elos(elos,results,k=10):
return [new_player_elo(i,elos,results,k) for i in range(0,len(results))]
########################################################################
## Function to create results array from single value in data ##########
########################################################################
def get_results(result):
if result == 1:
return [1.0,1.0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0]
else:
return [0.0,0.0,0.0,0.0,0.0,1.0,1.0,1.0,1.0,1.0]
#####################################################################################
## Gets ELOS from player dictionary and adds new players to dictionary if needed ####
#####################################################################################
def get_elos(new_players,player_dict):
output = []
for player in new_players:
try:
output.append(player_dict['elo'][player_dict['players'].index(player)])
except ValueError:
player_dict['players'].append(player)
player_dict['elo'].append(4000)
output.append(4000)
return (output,player_dict)
def update_elos(player_dict,player_array,new_player_elos):
for i in range(len(player_array)):
player_dict['elo'][player_dict['players'].index(player_array[i])] = new_player_elos[i]
return player_dict
def parse_match_data():
raw_data = f.readline().strip().split(',')
players = raw_data[0:10]
results = int(raw_data[10])
return players, results
###############################
## Run through one match ######
###############################
def rate_one_match(player_dict,k=10.0):
player_array, result = parse_match_data()
player_elos, player_dict = get_elos(player_array,player_dict)
result_array = get_results(result)
new_player_elos = new_elos(player_elos,result_array,k)
player_dict = update_elos(player_dict,player_array,new_player_elos)
print player_dict
return player_dict
## Start with a blank player_dict
player_dict = {
'players':[],
'elo':[]
}
print player_dict
loop_results = []
##Need a range function that take floats
## Taken from : http://stackoverflow.com/questions/7267226/range-for-floats
def frange(x, y, jump):
while x < y:
yield x
x += jump
k_array = [x for x in frange(1.0,3.0,0.1)]
print k_array
for k in k_array:
results_of_test = 0.0
with open('trainingdata.txt') as f:
for i in range(1000):
player_dict = rate_one_match(player_dict,k)
for i in range(500):
players, results = parse_match_data()
player_elos, player_dict = get_elos(players,player_dict)
if sum(player_elos[0:5]) > sum(player_elos[5:10]):
expected_result = 1
else:
expected_result = 2
if results == expected_result:
results_of_test += 1.0
loop_results.append(results_of_test/500.0)
print zip(k_array,loop_results)
## Seems k = 2 is best
##build final_dict from all dataset
player_dict = {
'players':[],
'elo':[]
}
with open('trainingdata.txt') as f:
for i in range(1500):
player_dict = rate_one_match(player_dict,2.0)
print player_dict
#############
## Code to be put in Hackerrank
#############
final_player_dict = {'players': ['Sven', 'Lone Druid', 'Venomancer', 'Clockwerk', 'Shadow Shaman', 'Invoker', 'Gyrocopter', 'Anti-Mage', 'Alchemist', 'Slark', 'Riki', 'Tinker', 'Puck', 'Leshrac', 'Nyx Assassin', 'Slardar', 'Sand King', 'Spectre', 'Necrolyte', 'Warlock', 'Mirana', 'Pudge', 'Magnus', 'Keeper of the Light', 'Rubick', 'Tidehunter', 'Queen of Pain', 'Faceless Void', 'Sniper', 'Centaur Warrunner', 'Treant Protector', 'Broodmother', 'Weaver', 'Troll Warlord', 'Drow Ranger', 'Razor', 'Kunkka', 'Zeus', 'Bane', 'Visage', 'Timbersaw', 'Silencer', 'Meepo', 'Morphling', 'Omniknight', 'Crystal Maiden', 'Lina', 'Dark Seer', 'Brewmaster', 'Ogre Magi', 'Disruptor', 'Juggernaut', 'Tiny', 'Enigma', 'Bounty Hunter', 'Earthshaker', 'Doom', 'Huskar', 'Dazzle', 'Naga Siren', "Nature's Prophet", 'Chen', 'Ursa', 'Wisp', 'Lion', 'Batrider', 'Chaos Knight', 'Beastmaster', 'Windrunner', 'Luna', 'Phantom Lancer', 'Witch Doctor', 'Storm Spirit', 'Jakiro', 'Clinkz', 'Phantom Assassin', 'Shadow Fiend', 'Ancient Apparition', 'Viper', 'Templar Assassin', 'Dragon Knight', 'Skeleton King', 'Lifestealer', 'Undying', 'Death Prophet', 'Enchantress', 'Lich', 'Outworld Devourer', 'Bloodseeker', 'Spirit Breaker', 'Axe', 'Pugna', 'Vengeful Spirit', 'Lycanthrope', 'Medusa', 'Shadow Demon', 'Night Stalker'], 'elo': [3994.1631613177406, 3980.9980456540366, 3983.817796799303, 4007.3983513952376, 3987.9011164109133, 3983.9927612704514, 4044.623605438212, 3979.0912748530395, 3974.206350247612, 3990.678756840047, 3973.2907564878, 4002.0670271028566, 3989.2588098288393, 3998.817766883756, 4071.4912134580104, 3997.7825542921814, 4019.1843498210924, 3998.8105926231538, 4020.6579499341874, 4071.215459557408, 4057.9849476317554, 3971.2330692043834, 4038.6612245908686, 4057.0014792231455, 3961.021783998894, 4019.089120919476, 4002.444113269398, 3955.985904679837, 4032.10176172715, 4015.6224536253703, 3964.9419514334472, 3979.8664689487564, 4005.766970263955, 4022.169228823354, 4053.84476860488, 4029.236405163548, 4014.878355740683, 4050.2559304327074, 4002.304498522973, 4012.9537922024215, 3934.3179404974903, 4022.0071727416434, 3944.7645484796344, 3999.7210288874135, 4038.3157375644914, 4019.7879438084656, 3973.523198919531, 4006.536646491849, 3996.8696884250585, 4026.8479684733, 3987.689902950351, 3981.9865978169664, 3987.11244029581, 4015.343690713302, 3976.2676375079154, 3987.1504456024004, 3994.6579655251326, 3987.5173244678263, 3997.8255744545845, 3990.6915826151417, 3981.2703586425714, 4009.403979361409, 3989.2169111789676, 3986.8418742532335, 3978.4427998515775, 3970.8141801136035, 3996.0834452168638, 4011.8954160874146, 4003.096422301421, 4003.761392908484, 4036.0923247627557, 3983.6464437271275, 4006.1928361237597, 4020.1079988317015, 3974.935849456535, 3982.0270210855138, 4040.7894659960934, 3959.9997326708835, 3996.241976692838, 3987.3946771626565, 3996.206439934385, 3988.5337350853238, 3990.9999587548996, 3966.7525873675017, 4003.6764388523507, 3953.364011969913, 4044.5426148002975, 3980.4996553778656, 3949.636143328877, 4027.949573030075, 3971.5581250899763, 3986.055345363048, 4047.2192715769793, 3999.2061709991654, 3947.9604365226355, 4019.8883647068105, 4021.949055353319]}
def parse_test_data():
raw_data = raw_input().strip().split(",")
players = raw_data[0:10]
return players
def get_elos(new_players,player_dict):
output = []
for player in new_players:
try:
output.append(player_dict['elo'][player_dict['players'].index(player)])
except ValueError:
player_dict['players'].append(player)
player_dict['elo'].append(4000)
output.append(4000)
return (output,player_dict)
n_go = int(raw_input())
for i in range(n_go):
players = parse_test_data()
player_elos, player_dict = get_elos(players,final_player_dict)
if sum(player_elos[0:5]) > sum(player_elos[5:10]):
print 1
else:
print 2
## Score of 9.13 - 2nd in UK! (first attempt with k=10 and training ratings on first 1000 rows)
## Updated Score of 14.2 (second attempt with k=2 and training ratings on first 1500 rows)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment