获得六名球员的所有组合

时间:2014-02-24 20:47:37

标签: ruby

我有六名球员。这意味着我有十五个独特的游戏:

players = [1, 2, 3, 4, 5, 6]
games = players.combination(2).to_a
# => [[1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [2, 3], [2, 4], [2, 5], 
#    [2, 6], [3, 4], [3, 5], [3, 6], [4, 5], [4, 6], [5, 6]]

我想将这些游戏随机分为5轮3.每个玩家每轮应该玩1场比赛,并且任何一对都不应该重复上一轮比赛。

在每一轮中,我尝试使用player1循环与player2随机选择whileeach,但我总是以无限循环结束。有什么建议吗?

所以这是代码(抱歉没有把它放在预告片中)。问题是,有时它确实有效并且给了我想要的结果,但有时它只是分解并且它被捕获在循环中。

def pick_pair(players)
    player1 = players[rand(players.length)]
    players.delete(player1)
    player2 = players[rand(players.length)]
    players.delete(player2)
    pair = [player1, player2]
    return pair.sort!
end

def check_round(all_rounds, current_round)
    repeat = false
    if all_rounds == []
        repeat = false
    else
        repeat = catch :repeat do
            k = 0
            all_rounds.each do |round|
                a_r_l = all_rounds.length
                round.each do |pair|
                    r_l = round.length
                    k += 1
                    z = 0
                    current_round.each do |new_pair|
                        #p "Comparing: #{pair} to #{new_pair}"
                        z += 1
                        if pair == new_pair
                            repeat = true
                            throw :repeat, repeat
                        elsif (k == a_r_l*r_l  and z == current_round.length and pair != new_pair)
                            repeat = false
                            throw :repeat, repeat
                        end
                    end
                end
            end
        end
     end
     return repeat
 end

players = [1,2,3,4,5,6]
all_rounds = []

for i in 1..(players.length-1)
    #p "Round: #{i}"
    players_d = players.dup
    current_round = catch :round do 
        check = true
        while check
            current_round = []
            for j in 1..(players.length/2)
                #p "Game: #{j}"
                pair = pick_pair(players_d)
                current_round << pair
            end
            p "Previous rounds: #{all_rounds}"
            p "Current round: #{current_round}"
            repeat = check_round(all_rounds, current_round)
            if repeat == false
                throw :round, current_round
            else
                players_d = players.dup
            end
        end
    end
   all_rounds << current_round
 end

嗨,

感谢您的帮助。我重写了代码,它似乎工作。它也更简单:

players = [1,2,3,4,5,6]
possible_games = players.combination(2).to_a
all_games = []

for i in 1..(players.length - 1)
    round = catch :round do
            check = true
            while check
                round = []
                for i in 1..(players.length/2)
                    pair = possible_games[rand(possible_games.length)]
                    round << pair
                end
                if round.flatten.uniq == round.flatten
                    round.each do |game|
                        possible_games.delete(game)
                    end
                    throw :round, round
                else
                end
            end
        end
    all_games << round.sort!
end
p all_games

2 个答案:

答案 0 :(得分:3)

基本上,您正在尝试随机组合并重试,直到该方案有效。它会偶尔成功,但有时会陷入僵局:

Round 1  2  3  4  5
      12 14 16 13 
      34 36 32 5??
      56 52 54 

在第4轮中,玩家5必须玩1或3玩家,但这不会发生因为3已经在玩1.您的脚本会一直重试直到时间结束。

这样的锦标赛被称为循环锦标赛;维基百科有an algorithm

答案 1 :(得分:1)

虽然严格来说,这里最好(最有效)的解决方案是使用steenslang建议的“循环”算法。

我建议采用一种更简单的方法,这种方法很有效且很直接。

基本上,该程序试图让每一轮每个玩家每轮玩一次。它遍历一个混合的组合数组并尝试将它们配对。如果无法进行组合,则会对阵列进行重新洗牌并再次尝试。

这很简单,效果很好。

另外,如果你需要的话,你可以改变玩家的数量而且它只是有效。

希望这会有所帮助:

players = [1, 2, 3, 4, 5, 6]
initial_games = players.combination(2).to_a.shuffle
players_sum = players.inject{|sum,x| sum + x }
all_rounds = []

games = initial_games
until games.empty?
  current_round = []
  games.each do |game| 
    if (current_round.flatten & game).empty?
      current_round << game
    end
  end
  current_round_sum = current_round.flatten.inject{|sum,x| sum + x } 
  if current_round_sum == players_sum
    all_rounds << current_round
    games = games - current_round
  else
    all_rounds = []
    games = initial_games.shuffle
  end
end

puts all_rounds.inspect  # this outputs 5 rounds of 3 games