Saltar al contenido

Algoritmo de torneo Round Robin en C#

Nuestro equipo de redactores ha estado horas investigando para dar resolución a tu interrogante, te dejamos la resolución de modo que nuestro deseo es resultarte de mucha apoyo.

Solución:

Esto debería ser bastante fácil de hacer usando aritmética modular:

ACTUALIZACIÓN 2: (Como se prometió algoritmo correcto)

public void ListMatches(List ListTeam)

    if (ListTeam.Count % 2 != 0)
    
        ListTeam.Add("Bye");
    

    int numDays = (numTeams - 1);
    int halfSize = numTeams / 2;

    List teams = new List();

    teams.AddRange(ListTeam.Skip(halfSize).Take(halfSize));
    teams.AddRange(ListTeam.Skip(1).Take(halfSize -1).ToArray().Reverse());

    int teamsSize = teams.Count;

    for (int day = 0; day < numDays; day++)
    
        Console.WriteLine("Day 0", (day + 1));

        int teamIdx = day % teamsSize;

        Console.WriteLine("0 vs 1", teams[teamIdx], ListTeam[0]);

        for (int idx = 1; idx < halfSize; idx++)
                       
            int firstTeam = (day + idx) % teamsSize;
            int secondTeam = (day  + teamsSize - idx) % teamsSize;
            Console.WriteLine("0 vs 1", teams[firstTeam], teams[secondTeam]);
        
    

que imprimiría los partidos del equipo de cada día.

Permítanme tratar de explicar rápidamente cómo funciona el algoritmo:

Noté que como estamos rotando todos los equipos excepto el primero, si ponemos todos los equipos en un array excepto el primero, entonces deberíamos leer el primer equipo de ese array usando el desplazamiento del índice basado en el día y haciendo aritmética modular para ajustarse correctamente. En la práctica estaríamos tratando que array como repitiéndose infinitamente en ambas direcciones y estaríamos deslizando nuestra vista incrementalmente hacia la derecha (o hacia la izquierda).

Sin embargo, hay un inconveniente, y es el hecho de que tenemos que ordenar los equipos de una manera muy particular para que esto funcione correctamente. De lo contrario, no obtenemos la rotación correcta. Debido a esto, también debemos leer sobre el segundo equipo coincidente de una manera muy peculiar.

La forma correcta de preparar tu lista es la siguiente:

  • Nunca ponga el primer equipo (Equipo #1) en la lista.
  • Tome la última mitad de la lista del equipo y colóquelos al frente de la lista.
  • Tome la primera mitad de la lista, inviértala y colóquelos en la lista (pero no en el Equipo #1).

Ahora, la forma correcta de leer la lista es la siguiente:

  • Para cada día, incremente el primer índice que está viendo en 1.
  • Para el primer equipo que vea en esa ubicación, haga coincidir ese equipo con el Equipo #1.
  • Para el próximo equipo en la lista ((day + idx) % numDays), normalmente lo emparejaríamos con el equipo que está compensado por la mitad del número de equipos menos 1 (menos 1 porque nos ocupamos del primer partido nosotros mismos). Sin embargo, dado que la segunda mitad de nuestra lista se preparó revirtiendo, debemos hacer coincidir ese desplazamiento en la segunda mitad revertida de la lista. Una forma más sencilla de hacerlo es observar que en esto equivale a hacer coincidir el mismo índice pero desde el final de la lista. Dada la corriente day compensación que es (day + (numDays - idx)) % numDays.

ACTUALIZACIÓN 3: No estaba feliz de que mi solución involucrara una selección, combinación, inversión de array elementos. Después de pensar en lo que implicaba mi solución, me di cuenta de que estaba demasiado obsesionado con mantener el orden de los equipos tal como estaba. Sin embargo, eso no es un requisito y uno puede obtener un horario diferente pero igualmente válido sin preocuparse por el pedido inicial. Todo lo que importa es el algoritmo de selección que describo en la segunda parte de mi explicación.

Así puedes simplificar las siguientes líneas:

teams.AddRange(ListTeam.Skip(halfSize).Take(halfSize));
teams.AddRange(ListTeam.Skip(1).Take(halfSize -1).ToArray().Reverse());

para:

teams.AddRange(ListTeam); // Copy all the elements.
teams.RemoveAt(0); // To exclude the first team.

Parece que quieres programar un torneo de todos contra todos. El artículo de wp contiene el algoritmo.

No veo dónde estás incluso tratando de girar el array. La permutación se verá así: 1 -> 2 -> 3 -> 4 ... -> n/2 - 1 -> n - 1 -> n - 2 -> n - 3 -> ... -> n /2 -> 1 (y 0 permanece fijo). Puede hacerlo en 2 bucles (fila superior e inferior).

Hice algunas mejoras en el bloque de código respondido que calcula horario de doble turno

GameEntities db = new GameEntities();


private void btnTeamFixtures_Click(object sender, RoutedEventArgs e)
    
        txtResults.Text = null;

        var allTeams = db.Team.Select(t => t.TeamName);

        int numDays = allTeams.Count() - 1;
        int halfsize = allTeams.Count() / 2;

        List temp = new List();
        List teams = new List();

        teams.AddRange(allTeams);
        temp.AddRange(allTeams);
        teams.RemoveAt(0);

        int teamSize = teams.Count;

        for (int day = 0; day < numDays * 2; day++)
        
            //Calculate1stRound(day);
            if (day % 2 == 0)
            
                txtResults.Text += String.Format("nnDay 0n", (day + 1));

                int teamIdx = day % teamSize;

                txtResults.Text += String.Format("0 vs 1n", teams[teamIdx], temp[0]);

                for (int idx = 0; idx < halfsize; idx++)
                
                    int firstTeam = (day + idx) % teamSize;
                    int secondTeam = ((day + teamSize) - idx) % teamSize;

                    if (firstTeam != secondTeam)
                    
                        txtResults.Text += String.Format("0 vs 1n", teams[firstTeam], teams[secondTeam]);
                    
                
            

            //Calculate2ndRound(day);
            if (day % 2 != 0)
            
                int teamIdx = day % teamSize;

                txtResults.Text += String.Format("nnDay 0n", (day + 1));

                txtResults.Text += String.Format("0 vs 1n", temp[0], teams[teamIdx]);

                for (int idx = 0; idx < halfsize; idx++)
                
                    int firstTeam = (day + idx) % teamSize;
                    int secondTeam = ((day + teamSize) - idx) % teamSize;

                    if (firstTeam != secondTeam)
                    
                        txtResults.Text += String.Format("0 vs 1n", teams[secondTeam], teams[firstTeam]);
                    
                
            
        
    

Si lo desea, puede crear 2 métodos y pasar un número entero (Día) como hice en las 2 líneas comentadas, para separar el código.

Si tiene alguna pregunta o sugerencia, no dude en responder.

Comentarios y calificaciones

Agradecemos que quieras añadir valor a nuestro contenido informacional asistiendo con tu experiencia en las referencias.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *