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我已经在……的问题中写过了,我找到了解决这个问题的方法……因为我找到的算法不是完美的,但结果仍然可以接受。无论如何,你的回答是我所需要的最准确的。谢谢你的详细解释-因为我发现的算法不是完美的,但是结果仍然可以接受。无论如何,你的回答是我所需要的最准确的。谢谢你的详细解释-