Skip to content

Instantly share code, notes, and snippets.

@dmitriy-sqrt
Last active December 29, 2015 15:09
Show Gist options
  • Save dmitriy-sqrt/7688990 to your computer and use it in GitHub Desktop.
Save dmitriy-sqrt/7688990 to your computer and use it in GitHub Desktop.
Tournament mix model
def logA( x, a )
return (Math.log(x)/Math.log(a))
end
def print_row(teams) #просто выводит команды на какомто этапе
teams.each_slice(2) do |team1, team2|
print team1.to_s + '-' + team2.to_s + " "
end
puts
end
def play_round(teams) #раунд #команды играют, команда с рейтингом выше(а у нас это просто индекс-меньше=круче) 100% выигрывает
winners = []
teams.each_slice(2) do |team1, team2|
winner = (team1 < team2) ? team1 : team2
winners << winner
end
winners
end
def play_tournament(teams, rating_limit) #турнир - играем раунды, пока не останется одна команда
round = 1
while teams.size > 1 do
line = "#{round})"
round+= 1
teams = play_round(teams)
teams.each_slice(2) do |team1, team2|
line << " #{team1.to_s}-#{team2.to_s} " #вывод пары команд
end
line << ' | row opt=' + row_optimum(teams) if teams.size > 1 #коефициент оптимальности ряда
line << ' | row t_opt=' + row_t_optimum(teams, rating_limit) if teams.size > 1 #коефициент оптимальности ряда
line << ' | row n_opt=' + row_n_optimum(teams) if teams.size > 1 if teams.size > 1 #коефициент оптимальности ряда
puts line
end
end
def row_optimum(teams) #оптимальность по макс различию индексов команд в парах
teams_optimum = ro = 0
teams.each_slice(2) do |team1, team2|
#teams_optimum = (team1-team2).abs #сумма НЕвзвешенных значений разности рейтингов команды
teams_optimum = (team1-team2).abs * (1.to_f/[team1, team2].min) #сумма взвешенных значений разности рейтингов команд
ro += teams_optimum
#puts "to:#{teams_optimum} for (#{team1}-#{team2})"
#для чего взвешивание?
#т.к. нам важны именно разница с соперниками для топовых команд, делаем веса пропорциональные их близости к вершине (к 1)
#тоесть нам важнее к примеру: команды 1 и 10 чем команды 30 и 40 (хотя разница в рейтинге у обоих 10)
end
ro.round(2).to_s
end
def row_t_optimum(teams, rating_limit) #подумать #оптимальность по кол-ву пройденых этапов топовыми командами
teams_optimum = rto = 0
teams.each do |team|
next if team==1 #всем пофиг на самую рейтинговую команду, она полюбому пройдет
#не уверен про веса тут, какой вариант верный
team_optimum = (team < rating_limit) ? (team - rating_limit).abs*(1.to_f/team) : 0 #чем выше команда к топу - тем важнее
#ИЛИ
#team_optimum = (team < rating_limit) ? 1.to_f/(team - rating_limit).abs : 0 #чем дальше команда от топа - тем важнее
rto += team_optimum
end
rto.round(2).to_s
end
def row_n_optimum(teams) #оптимальность по кол-ву топовых команд на этапе
res = teams & Array(1..teams.count) #пересечение состава текущих команд раунда и "идеальных команд"
res = (res.count.to_f)/(teams.max) #поправака на "топовость" команды
res.round(2).to_s
end
def sort_teams(teams) #тут тестируемая сортировка
teams.shuffle #random
#one_up_one_down_sort(teams) #oneuponedownsorting
#teams #return
end
###SORTING METHODS###
def one_up_one_down_sort(teams)
new_teams = []
n = teams.count
mid = n/2
teams = [''].concat teams #грязно хачим, чтобы индексы команд начинались с 1 а не с 0 (как стандартно в массивах)
for i in 1..n/4 do
new_teams << teams[i] << teams[n+1-i] #непарный шаг
new_teams << teams[mid + i] << teams[mid+1-i] #парный шаг
end
new_teams
end
initial_teams = Array(1..32)
teams = sort_teams(initial_teams)
rating_limit = 5 #за команды с каким рейтингом включительно мы "волнуемся", скольким важно участие в макс кол-ве этапов
puts "Teams count=#{teams.size}"
puts "Init row opt=" + row_optimum(teams)
print_row(teams)
play_tournament(teams, rating_limit)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment