Ruby on rails 如何根据评分将所有会员分成单独的公平团队?

Ruby on rails 如何根据评分将所有会员分成单独的公平团队?,ruby-on-rails,ruby,algorithm,Ruby On Rails,Ruby,Algorithm,我想根据球员的等级将他们分成不同的公平团队。例如,我有这样一个玩家列表: players = [{ name: "Qasim", rating: 1 }, { name: "Mahsam", rating: 7 }, { name: "Aj", rating: 3 }, { name: "Osman", rating: 6 }, { name: "Usama", rating: 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个团队,每个团队的总分都是一样的,成员也是一样的:

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
  }
]
A队B队C队D队 ======= ======= ======= ======= 卡卡:20欧文:15比拉尔:8马萨姆:7 卡西姆:1 Usama:2 Aj:3奥斯曼:6 我已经找到了解决这个问题的方法,但是很难将它转换成ruby代码。假设我们可以有8名以上的球员,球队的数量可以从2到4支不等

1.按收视率递减对所有玩家进行排序。 2.指定A队为最佳球员。 3.指定B队为下一名最佳球员。 4.指定C队为下一名最佳球员。 5.指定D队为次佳球员。 6.指定D队为次佳球员。 7.指定C队为下一名最佳球员。 8.指定B队为下一名最佳球员。 9指定A队为下一名最佳球员。 10去2号 11当我们没有球员时结束。 事实上,球队可以有2到4支球队,每支球队中的所有球员都必须相等,每支球队的总得分也必须相等或尽可能接近相等

球员可以是任何数字,并且必须可以被球队整除


例如,如果有两支球队,那么球员总数必须相等。如果是3支球队,则所有球员必须可以被3整除;如果是4支球队,则所有球员必须可以被4整除。

我们可以通过将散列排序为键来解决此问题

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名成员

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


谢谢。

我们可以通过将散列排序为键来解决此问题

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名成员

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


谢谢。

您可以实现下面描述的分配算法

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
nbr_teams = 4
flip = [true, false].cycle
  #=> #<Enumerator: [true, false]:cycle>
如果有两个团队,任务如下

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}]]
步骤如下

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
nbr_teams = 4
flip = [true, false].cycle
  #=> #<Enumerator: [true, false]:cycle>
我们可以将此枚举数转换为数组,以查看它将生成并传递给map的对象

继续

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)> 
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}] 

您可以实现下面描述的分配算法

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
nbr_teams = 4
flip = [true, false].cycle
  #=> #<Enumerator: [true, false]:cycle>
如果有两个团队,任务如下

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}]]
步骤如下

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
nbr_teams = 4
flip = [true, false].cycle
  #=> #<Enumerator: [true, false]:cycle>
我们可以将此枚举数转换为数组,以查看它将生成并传递给map的对象

继续

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)> 
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}] 

我更新了问题。。。你的意思是你想最小化最大和最小的差异吗?如果是这样,您需要说….=>对这正是我想要的。我觉得这是一个NP完全问题。我不确定这是否只是一个变种。或者如果它很特别,有自己的名字。你可能想看看一系列著名的组合优化问题。@CarySwoveland我已经在……的问题中写了它,我找到了解决这个问题的方法……我更新了问题。。。你的意思是你想最小化最大和最小的差异吗?如果是这样,您需要说….=>对这正是我想要的。我觉得这是一个NP完全问题。我不确定这是否只是一个变种。或者如果它很特别,有自己的名字。你可能想看看一系列著名的组合优化问题。@CarySwoveland我已经在……的问题中写过了,我找到了解决这个问题的方法……因为我找到的算法不是完美的,但结果仍然可以接受。无论如何,你的回答是我所需要的最准确的。谢谢你的详细解释-因为我发现的算法不是完美的,但是结果仍然可以接受。无论如何,你的回答是我所需要的最准确的。谢谢你的详细解释-