我目前有以下方法:
def generate_lineups(max_salary)
player_combos_by_position = calc_position_combinations
lineups = []
player_combos_by_position[:qb].each do |qb_set|
unless salary_of(qb_set) > max_salary
player_combos_by_position[:rb].each do |rb_set|
unless salary_of(qb_set, rb_set) > max_salary
lineups << create_team_from_sets(qb_set, rb_set)
end
end
end
end
return lineups
end
player_combos_by_position是一个哈希,其中包含按位置键入的玩家分组:
{ qb: [[player1, player2], [player6, player7]], rb: [[player3, player4, player5], [player8, player9, player10]] }
salary_of()
获取一组球员并计算他们的总薪水。
create_team_from_sets()
需要一组玩家并返回一个新的玩家团队
理想情况下,我想删除硬编码的嵌套循环,因为我不知道哪些位置可用。我认为递归是答案,但我很难绕过解决方案。任何想法将不胜感激。
有些答案建议使用Array#product
。这通常是一个优雅的解决方案,但我正在处理非常大的数据集(大约有161,000个WR组合和大约5000个RB组合单独形成)。在我的循环中,我使用unless salary_of(qb_set, rb_set) > max_salary
检查以避免进行不必要的计算,因为这样做了很多。我无法使用Array#product
执行此操作,因此组合需要很长时间才能组合在一起。我正在寻找早期排除组合并节省计算机周期。
答案 0 :(得分:1)
您可以使用Array#product
获取所有可能的阵容,然后选择预算范围内的阵容。这允许可变数量的职位。
first_pos, *rest = player_combos_by_position.values
all_lineups = first_pos.product(*rest)
#=> all possible lineups
lineups = all_lineups.
# select lineups within budget
select{|l| salary_of(*l) <= max_salary}.
# create teams from selected lineups
map{|l| create_team_from_sets(*l) }
其他选项:递归方法(未经测试但应该让您入门)
def generate_lineups(player_groups,max_salary)
first, *rest = player_groups
lineups = []
first.each do |player_group|
next if salary_of(player_group) > max_salary
if rest.blank?
lineups << player_group
else
generate_lineups(rest,max_salary).each do |lineup|
new_lineup = create_team_from_sets(player_group, *lineup)
lineups << new_lineup unless salary_of(*new_lineup) > max_salary
end
end
end
return lineups
end
用法:
lineups = generate_lineups(player_combos_by_position.values,max_salary)
答案 1 :(得分:1)
阅读完编辑后,我看到了您的问题。在这里,我修改了我的代码,向您展示如何为每个职位组以及整个团队强加每个组合的工资限制。这有帮助吗?您可能需要考虑将数据放在数据库中并使用Rails。
team_max_salary = 300
players = {player1: {position: :qb, salary: 15, rating: 9}, player2: {postion: :rb, salary: 6, rating: 6},...}
group_info = {qb: {nplayers: 2, max_salary: 50}, rb: {nplayers: 2, max_salary: 50}, ... }
groups = group_info.keys
players_by_group = {}
groups.each {|g| players_by_group[g] = []}
players.each {|p| players_by_group[p.position] << p}
combinations_for_team = []
groups.each do |g|
combinations_by_group = players_by_group[g].combinations(group_info[g][:nplayers]).select {|c| salary(c) <= group_info[g][:max_salary]}
# Possibly employ other criteria here to further trim combinations_by_group
combinations_for_team = combinations_for_team.product(combinations_by_group).flatten(1).select {|c| salary(c) <= team_max_salary}
end
我可能错过了flatten(1)
。注意我已经制作了玩家键符号(例如:AaronRogers`),但你当然可以使用字符串。