1

I have an upcoming Fifa Tournament and I've written a program that prints out the possible matchup's. The problem is that it is not logically sorted, meaning some players would have to play 5-6 sequential games while other would have to wait 6 games. I would like to get the following result:

player 1 - player 2
player 3 - player 4
player 5 - player 6
player 1 - player 3
player 2 - player 4

and so on. This is what I have at the moment:

public class Fifa {

public static void main(String[] args) {
    String[] players= {"Jens", "Dane", "Keppens", "Roel", "John", "Onslo", "JonasDB", "Bellon", "Sander"};
    String[] players2 = {"Jens", "Dane", "Keppens", "Roel", "John", "Onslo", "JonasDB", "Bellon", "Sander"};


    Multimap<String, String> fixtures = LinkedHashMultimap.create();

    for(int i = 0; i < players.length; i++){
        for (int j = 0; j < players.length; j++){
            if(!players[i].equals(players2[j])) {
                if(!fixtures.containsKey(players2[j]))
                fixtures.put(players[i], players2[j]);
            }
        }
    }

    for(Map.Entry map : fixtures.entries()){
        String key = map.getKey().toString();
        Object value = map.getValue();
        System.out.println(key + " - " + value);
    }

But here is what this prints out:

Jens - Dane
Jens - Keppens
Jens - Roel
Jens - John
Jens - Onslo
Jens - JonasDB
Jens - Bellon
Jens - Sander
Dane - Keppens
Dane - Roel
Dane - John
Dane - Onslo
Dane - JonasDB
Dane - Bellon
Dane - Sander
Keppens - Roel
Keppens - John
Keppens - Onslo
Keppens - JonasDB
Keppens - Bellon
Keppens - Sander
Roel - John
Roel - Onslo
Roel - JonasDB
Roel - Bellon
Roel - Sander
John - Onslo
John - JonasDB
John - Bellon
John - Sander
Onslo - JonasDB
Onslo - Bellon
Onslo - Sander
JonasDB - Bellon
JonasDB - Sander
Bellon - Sander

I used a Multimap because I needed multiple keys with the same value.

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
Audiosleef
  • 137
  • 3
  • 14
  • In your example, when does 2 and 3 play against each other? Do they? Would something like 1-2, 2-3, 3-4, 4-5, 5-6, 1-3, 2-4, etc. also be fine? Because that can be done really easily by looping over distance instead of index. – Bernhard Barker Apr 06 '17 at 11:42
  • They would eventually play each other yes. The "issue" with that sorting logic is that there would always be a player playing to consecutive games, but it's better then my implementation. How would you implement this? – Audiosleef Apr 06 '17 at 11:46

1 Answers1

2

A somewhat simple approach would be to loop over the distances, so we first output all match-ups of distance 1, then 2, then 3, etc.

The basic version of this:

for(int dist = 1; dist < players.length; dist++)
for(int i = 0; i + dist < players.length; i++)
    System.out.println(players[i] + " - " + players[i+dist]);

This would give match-ups in the following order: (grouped by distance for brevity)

0 - 1, 1 - 2, 2 - 3, 3 - 4, 4 - 5, 5 - 6, 
0 - 2, 1 - 3, 2 - 4, 3 - 5, 4 - 6, 
0 - 3, 1 - 4, 2 - 5, 3 - 6, 
0 - 4, 1 - 5, 2 - 6, 
0 - 5, 1 - 6, 
0 - 6, 

If you want to avoid the scenario in the first line where everyone plays 2 games in a row, you can separate that out and split it by odd and even numbers:

for(int i = 0; i < players.length-1; i+=2)
    System.out.println(players[i] + " - " + players[i+1]);
for(int i = 1; i < players.length-1; i+=2)
    System.out.println(players[i] + " - " + players[i+1]);

for(int dist = 2; dist < players.length; dist++)
for(int i = 0; i + dist < players.length; i++)
    System.out.println(players[i] + " - " + players[i+dist]);

That gives match-ups in this order:

0 - 1, 2 - 3, 4 - 5, 
1 - 2, 3 - 4, 5 - 6, 
0 - 2, 1 - 3, 2 - 4, 3 - 5, 4 - 6, 
0 - 3, 1 - 4, 2 - 5, 3 - 6, 
0 - 4, 1 - 5, 2 - 6, 
0 - 5, 1 - 6, 
0 - 6, 

A variation on this would be wrapping around and only looping over half the distance (with a special case to avoid the distance = length/2 line duplicating match-ups for even-sized arrays).

for(int i = 0; i < players.length; i+=2)
    System.out.println(players[i] + " - " + players[(i+1)%players.length]);
for(int i = 1; i < players.length; i+=2)
    System.out.println(players[i] + " - " + players[(i+1)%players.length]);

for(int dist = 2; dist < (players.length+1)/2; dist++)
for(int i = 0; i < players.length; i++)
    System.out.println(players[i] + " - " + players[(i+dist)%players.length]);

if (players.length % 2 == 0)
    for(int i = 0; i < players.length/2; i++)
        System.out.println(players[i] + " - " + players[i+players.length/2]);

The match-ups would look like this:

0 - 1, 2 - 3, 4 - 5, 6 - 0, 
1 - 2, 3 - 4, 5 - 6, 
0 - 2, 1 - 3, 2 - 4, 3 - 5, 4 - 6, 5 - 0, 6 - 1, 
0 - 3, 1 - 4, 2 - 5, 3 - 6, 4 - 0, 5 - 1, 6 - 2, 
Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
  • That is exactly what I wanted, thank you very much ! Good to know it was possible with just one String array, didn't need a hashmap after all ! I would upvote you but my reputation is too low. – Audiosleef Apr 06 '17 at 12:44