I have been searching everywhere, including the Stack Overflow archives, for an answer of how to do this, I tried rolling my own, but have come up short, so I decided I would post my request here.
I need to take an arbitrary (even) number of items in an array and return with item paired with another item in the array. I need the output of the code to be the same as the output example I have included below.
Input:
('A'..'H').to_a
Output:
[[['A','H'], ['B','G'], ['C','F'], ['D','E']], [['A','G'], ['B','F'], ['C','E'], ['D','H']], [['A','F'], ['B','E'], ['C','D'], ['G','H']], [['A','E'], ['B','D'], ['C','H'], ['F','G']], [['A','D'], ['B','C'], ['E','G'], ['F','H']], [['A','C'], ['B','H'], ['D','G'], ['E','F']], [['A','B'], ['C','G'], ['D','F'], ['E','H']]]
Any ideas?
Here's what I have done so far. It's a bit dirty, and it's not returning in the order I need.
items = ('A'..'H').to_a combinations = [] 1.upto(7) do |index| curitems = items.dup combination = [] 1.upto(items.size / 2) do |i| team1 = curitems.delete_at(0) team2 = curitems.delete_at(curitems.size - index) || curitems.delete_at(curitems.size - 1) combination << [team1, team2] end combinations << combination end pp combinations
The output is close, but not in the right order:
[[["A", "H"], ["B", "G"], ["C", "F"], ["D", "E"]], [["A", "G"], ["B", "F"], ["C", "E"], ["D", "H"]], [["A", "F"], ["B", "E"], ["C", "D"], ["G", "H"]], [["A", "E"], ["B", "D"], ["C", "H"], ["F", "G"]], [["A", "D"], ["B", "C"], ["E", "G"], ["F", "H"]], [["A", "C"], ["B", "H"], ["D", "E"], ["F", "G"]], [["A", "B"], ["C", "G"], ["D", "H"], ["E", "F"]]]
You'll notice that my code gets me two D<->H combinations (last line and second line) and that won't work.
My understanding of the OP's requirements [FM]:
- Given
N
teams (for example, 8 teams:A..H
). - Create a tournament schedule,
consisting of
R
rounds of play (7 in our example) andG
games (28 in our example). - Where every team plays every other team exactly once.
- Where every team plays once in each round.
- And (the hard part) where the ordering of games within a round works like this:
- The top-ranked team (A) plays the low-ranked team (H) first.
- If a candidate matchup is rejected
for violating the no-repeat rule, put
the low-ranked team on the
"back-burner" and form the other
matchups first. Then matchup the
back-burner teams using the same
rules. (For example: in Round 2, the
first candidate matchup,
A-H
, is rejected as a repeat, so Game 1 will beA-G
, andH
will sit on the back burner, to be paired withD
as the last game in the round). - When adding teams to the back-burner, add them to the front of that list (i.e., preserve rank ordering on the back-burner as well).
- Note: Round 5 is the tricky one. The
first 2 games are straightforward.
The 3rd game would then be
E-H
; however, that creates a scenario where the 4th game would be a repeat (F-G
). So the algorithm needs to backtrack, reject theE-H
pairing and instead go forE-G
in the 3rd game.