6
votes

Tri des graines de tournoi

Je fais une application Web de support de support unique / Double d'élimination optimale HTML / JS. J'ai du mal à comprendre comment attribuer les matchs de premier tour d'une liste d'équipes / joueurs ensemencées. Par exemple, dans un support de 8 joueurs, les matchs de premier tour sont les suivants:

1v8 4v5 2v7 3v6

en termes plus génériques, les graines peuvent être considérées comme une matrice (lorsque j'attribuais des équipes aux correspondances en les éclaboussant un tableau): 1,2,3,4,5,6,7,8

Qui doit être trié pour: 1,8,4,5,2,7,3,6

Pour clarifier, les graines supérieures doivent avoir la distance maximale entre elles dans la matrice triée, c'est que dans un support sans suppression, les graines inférieures sont assommées d'abord et des matchs avec des graines hautes se produisent aussi tard que possible. . Practical Termes, pensez à un tournoi de tennis, où vous voulez empêcher les 4 meilleurs joueurs d'un support de 16 ou 32, etc. de se jouer jusqu'à la finale. Donc, la sortie de matrice correcte pour un 16 le support de semences est la suivante:

1,16,8,9,4,13,5,12,2,15,7,10,3,14,6,11

qui se traduit par les matchs suivants du 1er round:

1v16 8v9 4v13 5v12 2V15 7V10 3V14 6V11

Merci à Matt Ball pour l'algorithme correct pour un 8 support de graines


1 commentaires

Donc, l'ordre des paires compte réellement, est-ce correct?


6 Réponses :


2
votes

Ceci n'est probablement pas aussi efficace que la réponse S> @ Alex à l'aide d'une fonction de tri code> personnalisée code>, mais plus facile à écrire et à comprendre:

// Also assumes that seeds.length is an even number
var seeds = [1, 2, 3, 4, 5, 6, 7, 8],
    numSeeds = seeds.length,
    stop = numSeeds >> 1,
    temp;

for (var i=1; i<stop; i=i+2)
{
    temp = seeds[i];
    seeds[i] = seeds[numSeeds-i];
    seeds[numSeeds-i] = temp;
}

// seeds is now [1, 8, 3, 6, 5, 4, 7, 2]


4 commentaires

Merci! La première solution n'est pas tout à fait juste car les 1er et la 2ème graines, en supposant qu'aucune suppression, se rencontrent plus tôt que le dernier match indésirable. La deuxième solution est correcte pour un support avec 8 graines, mais il est légèrement éteint s'il y a 16 équipes que 1v3 aura lieu au second tour, ce qui signifie que dans le classement final, la graine 5 finira au-dessus de la graine 3 (comme la graine 5 Il suffit de battre la graine 7) voir Cet exemple . C'est ma faute pour ne pas fournir suffisamment de contexte


Désolé, je ne suis pas un beaucoup pour le sport: P en tout cas, ma réponse illustre au moins l'approche que vous pourriez utiliser pour un plus grand nombre de graines?


ça va bien, ma question est assez déroutante. Oui, je vais modifier avec la logique de tri pour voir si je peux répartir uniformément les hautes graines à travers le tableau


Semble aussi correct. Cependant, vous préférez peut-être vous retrouver avec des allumettes dans cet ordre spécifique: (1, 16), (9, 8), (5, 12), (13, 4), (3, 14), (11, 6) , (7, 10), (15, 2). Voir ma réponse ici: Stackoverflow.com/a/45572051/760777



2
votes

J'ai monté une solution, mais c'est en dehors de la portée des "tableaux de tri".

Le code (JavaScript) est chez http://jsbin.com/ukomo5/2/edit: a>.

En termes de base, l'algorithme suppose qu'aucune soulevée ne se produira dans le support, donc les graines 1 et 2 devraient se rencontrer lors du dernier tour. Il itère à travers chaque graine de chaque tour (à partir de la grande finale pré-calculée, de travail en arrière), calculant la graine inconnue dans le match dans la partie précédente que la graine actuelle (dans l'itération) avait gagné. Cela peut être fait car étant donné une graine et un nombre rond, vous pouvez déterminer ce que l'autre graine devrait être:

Autres semences = nombre de graines au rond + 1 - la graine connue

illustrer, en demi-finale:

demi-final 1 (où la graine connue est 1): Autres graines = 4 + 1 - 1 = 4

semi-finale 2 (où la graine connue est 2): Autres graines = 4 + 1 - 2 = 3

Je viens de remarquer ce modèle en regardant un support "NO UPSETS", j'avais dessiné.

Dans l'itération finale (c.-à-d. 1) toutes les graines et leur position sont connues, prêtes à être attribuées à des correspondances. La matrice triée correcte est ci-dessous:

1,16,8,9,4,13,5,12,2,15,7,10,3,14,6,11

Merci encore à Matt Ball qui a proposé une solution correcte pour les petits supports (il est difficile d'indiquer le problème et la solution souhaitée sans contexte détaillé, que je n'ai pas fait complètement dans ma question initiale).

Si quelqu'un a une autre solution ou une version plus élégante de ma solution, faites-le nous savoir!



11
votes

Les idées des joueurs correspondants du haut et du bas sont correctes mais pas tout à fait complète. Le faire une fois fonctionne bien pour le premier tour: xxx pré>

... Mais au second tour, la graine 1 rencontre la graine 2 et 3 rencontre 4. Nous devons faire le premier / dernier shuffle pour chaque tour. Première fois, nous déplaçons chaque élément individuellement fort>. Deuxième fois, nous déplacons chaque paire forte> d'éléments. Troisièmement, la troisième fois que nous déplacons groupes de quatre forts>, etc., jusqu'à ce que notre taille de groupe soit graines.Length / 2 code>. Comme: p> xxx pré>

Voici ce que la matrice ressemblera à la travers des itérations (la parenthèse indique la taille croissante du groupe): P>

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16

(1, 16),  (2, 15),  (3, 14),  (4, 13),   (5, 12),   (6, 11),   (7, 10),   (8, 9)

(1, 16, 8, 9),  (2, 15, 7, 10),  (3, 14, 6, 11),  (4, 13, 5, 12)

(1, 16, 8, 9, 4, 13, 5, 12),  (2, 15, 7, 10, 3, 14, 6, 11)


1 commentaires

Semble correct. Cependant, vous préférez peut-être vous retrouver avec des allumettes dans cet ordre spécifique: (1, 16), (9, 8), (5, 12), (13, 4), (3, 14), (11, 6) , (7, 10), (15, 2). Voir ma réponse ici: Stackoverflow.com/a/45572051/760777



2
votes

Voici l'algorithme que j'ai développé. L'étape 1 est de dessiner une table avec autant de lignes qu'il existe des équipes (arrondies à une puissance de 2) et autant de colonnes que nécessaire pour représenter le nombre d'équipes en binaire. Dis, il y a 8 équipes. La table ressemblera d'abord à ceci (les points représentent des bordures de cellules horizontales):

. . . | | | | . . . | | | | . . . | | | | . . . | | | | . . . | | | | . . . | | | | . . . | | | | . . . | | | | . . .

Les colonnes sont numérotées à partir de la gauche dans l'ordre croissant. Pour chaque colonne, mettez un astérisque tous les 2 ^ (numéro de colonne). C'est-à-dire toutes les 2èmes rangées de la colonne 1, toutes les 4èmes rangées de la colonne 2 etc.

. . . | | | | . . . | | | | *. . | | | | . . . | | | | * *. | | | | . . . | | | | *. . | | | | . . . | | | |


Commencez avec un 0 dans chaque colonne de la 1ère rangée. Par la suite, pour des lignes successives dans chaque colonne bascule de 0-1 et 1-0 à moins d'un astérisque dans cette rangée. C'est le résultat:

. . . | 0 | 0 | 0 | . . . | 1 | 1 | 1 | *. . | 1 | 0 | 0 | . . . | 0 | 1 | 1 | * *. | 0 | 1 | 0 | . . . | 1 | 0 | 1 | *. . | 1 | 1 | 0 | . . . | 0 | 0 | 1 |


La dernière étape consiste à évaluer chaque ligne de traitement de la chaîne de 0 et 1 sous forme de numéro binaire. Cela entraînera des valeurs de 0 à 7. Ajout de 1 à chaque résultat des valeurs de 1 à 8. Celles-ci correspondent aux semis.

. . . | 0 | 0 | 0 | + 1 = 1 . . . | 1 | 1 | 1 | + 1 = 8 *. . | 1 | 0 | 0 | + 1 = 5 . . . | 0 | 1 | 1 | + 1 = 4 * *. | 0 | 1 | 0 | + 1 = 3 . . . | 1 | 0 | 1 | + 1 = 6 *. . | 1 | 1 | 0 | + 1 = 7 . . . | 0 | 0 | 1 | + 1 = 2


Chaque paire de graines sont les allumettes à jouer dans l'ordre. c'est à dire. 1-8, 5-4, 3-6 et 7-2. Ceci est extensible à n'importe quel nombre de graines. Lorsque les byes doivent être insérés en raison du nombre d'entrées étant inférieures à une puissance de 2, elles prennent les valeurs de semences les plus élevées. par exemple. S'il n'y avait que 28 entrées, les byes prennent les positions attribuées à 29, 30, 31 et 32.


2 commentaires

Veuillez travailler dans un exemple javascript. J'aime votre approche.


Je veux juste dire que cette solution est géniale! J'ai écrit une implémentation de rubis ici: Stackoverflow.com/a/59378639/352085



3
votes

J'ai écrit une solution en PHP (voir https://stackoverflow.com/a/45566890/760777 ). Voici la version JavaScript.

Il renvoie toutes les graines dans les bonnes positions forte>. Les matchs sont les mêmes que dans son exemple, mais dans un ordre plus jolie EM>, la graine 1 et la graine numéro 8 sont à l'extérieur du schéma (comme vous le voyez dans des tournois de tennis). P> S'il n'y a pas de bouleversement (ce qui signifie qu'un joueur ensemencé supérieur gagne toujours à partir d'un joueur grillé inférieur), vous vous retrouverez avec une graine 1 vs graine 2 en finale. p>

Cela fait en réalité deux choses plus: p>

  1. Il montre le bon ordre (qui est une condition nécessaire pour mettre les byes dans les bonnes positions) p> li>

  2. Il remplit les byes dans les bonnes positions (si nécessaire) p> li> ol>

    Une explication parfaite sur ce qu'on doit ressembler à un seul support d'élimination: http://blog.playdriven.com/2011/articles/Le-not-so-simple-single-élimination-Avantage-evantage-Avantage-Éxéivant/ P >

    Exemple de code pour 8 participants: p>

    p>

    var NUMBER_OF_PARTICIPANTS = 8; // Set the number of participants
    
    if (!String.prototype.format) {
      String.prototype.format = function() {
        var args = arguments;
        return this.replace(/{(\d+)}/g, function(match, number) { 
          return typeof args[number] != 'undefined' ? args[number] : match;
        });
      };
    }
    
    var participants = Array.from({length: NUMBER_OF_PARTICIPANTS}, (v, k) => k + 1) ;
    var bracket = getBracket(participants);
    
    console.log(bracket);
    
    function getBracket(participants)
    {
      var participantsCount = participants.length;	
      var rounds = Math.ceil(Math.log(participantsCount)/Math.log(2));
      var bracketSize = Math.pow(2, rounds);
      var requiredByes = bracketSize - participantsCount;
    	
      console.log("Number of participants: {0}".format(participantsCount));
      console.log("Number of rounds: {0}".format(rounds));
      console.log("Bracket size: {0}".format(bracketSize));
      console.log("Required number of byes: {0}".format(requiredByes));    
        
      if(participantsCount < 2) {
        return [];
      }
        
      var matches = [[1,2]];
      
      for(var round = 1; round < rounds; round++) {
        var roundMatches = [];
        var sum = Math.pow(2, round + 1) + 1;
        
        for(var i = 0; i < matches.length; i++) {
          var home = changeIntoBye(matches[i][0], participantsCount);
          var away = changeIntoBye(sum - matches[i][0], participantsCount);
          roundMatches.push([home, away]);
          home = changeIntoBye(sum - matches[i][1], participantsCount);
          away = changeIntoBye(matches[i][1], participantsCount);
          roundMatches.push([home, away]);
        }
        matches = roundMatches;   
        
      }   
      
      return matches;    
    }
    
    function changeIntoBye(seed, participantsCount)
    {
        //return seed <= participantsCount ?  seed : '{0} (= bye)'.format(seed);  
        return seed <= participantsCount ?  seed : null;
    }


1 commentaires

le lien vers le blog est cassé, par une occasion, savez-vous où il s'est déplacé



0
votes

J'étais vraiment intrigué et impressionné par l'algorithme de Cliff ici . Je pense que c'est très intelligent. Voici une simple mise en œuvre que j'ai écrite dans Ruby. Les byes sont retournés comme -1.

seed(8)
=> [1, 8, 5, 4, 3, 6, 7, 2]

seed(6)
=> [1, -1, 5, 4, 3, 6, -1, 2]


0 commentaires