如何根据评级将所有成员划分为个别公平的团队?

问题描述 投票:1回答:2

我想根据他们的评分将球员划分为个人公平的球队。例如,我有一个像这样的球员列表:

players = [{
    name: "Qasim",
    rating: 1
  }, {
    name: "Mahsam",
    rating: 7
  }, {
    name: "Aj",
    rating: 3
  }, {
    name: "Osman",
    rating: 6
  }, {
    name: "Usama",
    rating: 2
  }, {
    name: "Bilal",
    rating: 8
  }, {
    name: "Kaka",
    rating: 20
  }, {
    name: "Owen",
    rating: 15
  }
]

我想将他们分成4个队伍,得分最高,同样也是这样的成员:

Team A       Team B       Team C     Team D
=======      =======      =======    =======
Kaka: 20     Owen: 15     Bilal: 8   Mahsam: 7
Qasim: 1     Usama: 2     Aj: 3      Osman: 6

我找到了解决这个问题的方法,但很难将其转换为ruby代码。假设我们可以有超过8名球员,球队的数量可以从2到4支球队不等。

1. Sort all players by their ratings descendingly.
2. Assign team A the best player.
3. Assign team B the next best player.
4. Assign team C the next best player.
5. Assign team D the next best player.
6. Assign team D the next best player.
7. Assign team C the next best player.
8. Assign team B the next best player.
9. Assign team A the next best player.
10. Go to 2
11. End when we're out of players.

有人可以帮忙吗?提前致谢。

注意:实际上球队可以从2到4支球队不等,每支球队的所有球员必须相等,每支球队的总评分必须相等或尽可能接近相等。

玩家可以是任何数字,并且必须可以被团队整除。

EX:如果2支球队,总球员必须是均匀的。如果3支队伍,总队员必须可以被3整除,如果有4支队伍,则总队员必须可以被4整除。欢迎任何类型的答案:)

ruby-on-rails ruby algorithm
2个回答
3
投票

您可以按如下方式实现您描述的分配算法。

def assign(nbr_teams, players)
  flip = [true, false].cycle
  players.
    sort_by { |p| p[:rating] }.
    each_slice(nbr_teams).
    map { |a| flip.next ? a.reverse : a }.
    transpose
end

assign(4, players)
  #=> [[{:name=>"Osman",  :rating=>6}, {:name=>"Mahsam", :rating=>7}],
  #    [{:name=>"Aj",     :rating=>3}, {:name=>"Bilal",  :rating=>8}],
  #    [{:name=>"Usama",  :rating=>2}, {:name=>"Owen",   :rating=>15}],
  #    [{:name=>"Qasim",  :rating=>1}, {:name=>"Kaka",   :rating=>20}]] 

如果有2支队伍,任务如下。

assign(2, players)
  #=> [[{:name=>"Usama",  :rating=>2}, {:name=>"Aj",     :rating=>3},
  #     {:name=>"Bilal",  :rating=>8}, {:name=>"Owen",   :rating=>15}],
  #    [{:name=>"Qasim",  :rating=>1}, {:name=>"Osman",  :rating=>6},
  #     {:name=>"Mahsam", :rating=>7}, {:name=>"Kaka",   :rating=>20}]]

步骤如下。

nbr_teams = 4
flip = [true, false].cycle
  #=> #<Enumerator: [true, false]:cycle>

Array#cycle的工作方式如下:flip.next #=> trueflip.next #=> falseflip.next #=> true等。继续,

a = players.sort_by { |p| p[:rating] }
  #=> [{:name=>"Qasim",  :rating=>1},  {:name=>"Usama", :rating=>2},
  #    {:name=>"Aj",     :rating=>3},  {:name=>"Osman", :rating=>6},
  #    {:name=>"Mahsam", :rating=>7},  {:name=>"Bilal", :rating=>8},
  #    {:name=>"Owen",   :rating=>15}, {:name=>"Kaka", :rating=>20}] 
b = a.each_slice(nbr_teams)
  #=> #<Enumerator:
  #     [{:name=>"Qasim",  :rating=>1},  {:name=>"Usama", :rating=>2},
  #      {:name=>"Aj",     :rating=>3},  {:name=>"Osman", :rating=>6},
  #      {:name=>"Mahsam", :rating=>7},  {:name=>"Bilal", :rating=>8},
  #      {:name=>"Owen",   :rating=>15}, {:name=>"Kaka",  :rating=>20}]
  #     :each_slice(4)> 

我们可以将这个枚举器转换为数组,以查看它将生成的对象并传递给map

b.to_a
  #=> [[{:name=>"Qasim",  :rating=>1},  {:name=>"Usama", :rating=>2},
  #     {:name=>"Aj",     :rating=>3},  {:name=>"Osman", :rating=>6}], 
  #    [{:name=>"Mahsam", :rating=>7},  {:name=>"Bilal", :rating=>8}, 
  #     {:name=>"Owen",   :rating=>15}, {:name=>"Kaka",  :rating=>20}]] 

继续,

c = b.map { |a| flip.next ? a.reverse : a }
  #=> [[{:name=>"Osman",  :rating=>6},  {:name=>"Aj",    :rating=>3},
  #     {:name=>"Usama",  :rating=>2},  {:name=>"Qasim", :rating=>1}],
  #    [{:name=>"Mahsam", :rating=>7},  {:name=>"Bilal", :rating=>8},
  #     {:name=>"Owen",   :rating=>15}, {:name=>"Kaka",  :rating=>20}]] 
c.transpose
  #=> [[{:name=>"Osman", :rating=>6}, {:name=>"Mahsam", :rating=>7}],
  #    [{:name=>"Aj",    :rating=>3}, {:name=>"Bilal",  :rating=>8}],
  #    [{:name=>"Usama", :rating=>2}, {:name=>"Owen",   :rating=>15}],
  #    [{:name=>"Qasim", :rating=>1}, {:name=>"Kaka",   :rating=>20}]] 

可能需要将结果转换为散列数组。

assign(4, players).map { |a| a.map { |h| [h[:name], h[:rating]] }.to_h }
  #=> [{"Osman"=>6, "Mahsam"=>7},
  #    {"Aj"   =>3, "Bilal" =>8},
  #    {"Usama"=>2, "Owen"  =>15},
  #    {"Qasim"=>1, "Kaka"  =>20}] 

1
投票

我们可以通过评级作为关键来解决它对哈希进行排序

players.sort_by { |k| k[:rating] }

现在你已经排序了数组。

您可以迭代一半长度的数组,并在一个团队中推送i元素和length-i元素,在这种情况下,您有4个团队。

def divide_teams players
   players = players.sort_by { |k| k[:rating] } # sorted
   len = players.length
   teams = Hash.new(0)
   (len/2).times do |i|
      teams["team#{i+1}"] = [players[i], players[len-i-1]]
   end
   teams
end

divide_teams players

=> {"team1"=>[{:name=>"Qasim", :rating=>1}, {:name=>"Kaka", :rating=>20}],
 "team2"=>[{:name=>"Usama", :rating=>2}, {:name=>"Owen", :rating=>15}],
 "team3"=>[{:name=>"Aj", :rating=>3}, {:name=>"Bilal", :rating=>8}],
 "team4"=>[{:name=>"Osman", :rating=>6}, {:name=>"Mahsam", :rating=>7}]}

现在,我假设有4个团队,每个团队有2个成员。

如果功能团队是动态变量,您可以根据需要更改功能。

谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.