0

我目前有以下方法:

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,因此这些组合需要很长时间才能组合在一起。我正在寻找尽早排除组合并节省计算机周期的方法。

4

2 回答 2

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)
于 2013-09-27T21:42:49.647 回答
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`),但您当然可以使用字符串来代替。

于 2013-09-27T21:56:08.437 回答