Как разделить всех участников на отдельные честные команды на основе их рейтингов? - PullRequest
1 голос
/ 10 апреля 2019

Я хочу разделить игроков на отдельные честные команды в зависимости от их рейтинга.Например, у меня есть список игроков, подобных этому:

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. Любой тип ответа приветствуется:)

Ответы [ 2 ]

3 голосов
/ 10 апреля 2019

Вы можете реализовать алгоритм назначения, который вы описываете следующим образом.

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>

Массив # цикл работает так: flip.next #=> true, flip.next #=> false, flip.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 голос
/ 10 апреля 2019

Мы можем решить эту проблему, отсортировав хеш по рейтингу как ключ

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 члена.

вы можете изменить функцию в соответствии с вашими потребностями, если функция team является динамической переменной.

Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...