Question

Ceci fait partie d'un programme qui analyse les chances du poker, en particulier du Texas Hold'em.J'ai un programme dont je suis satisfait, mais il a besoin de quelques petites optimisations pour être parfait.

J'utilise ce type (entre autres bien sûr) :

  type
    T7Cards = array[0..6] of integer;

Il y a deux choses à propos de ce tableau qui peuvent être importantes pour décider comment le trier :

  1. Chaque élément est une valeur de 0 à 51.Aucune autre valeur n'est possible.
  2. Il n'y a pas de doublons.Jamais.

Avec ces informations, quel est le absolument le plus rapide comment trier ce tableau ?J'utilise Delphi, donc le code pascal serait le meilleur, mais je peux lire le C et le pseudo, quoique un peu plus lentement :-)

Pour le moment, j'utilise le tri rapide, mais le plus drôle, c'est que ce n'est presque pas plus rapide que le tri à bulles !Possible en raison du petit nombre d'articles.Le tri compte pour près de 50 % du temps total d’exécution de la méthode.

MODIFIER:

Mason Wheeler a demandé pourquoi il est nécessaire d'optimiser.L’une des raisons est que la méthode sera appelée 2 118 760 fois.

Informations de base sur le poker :Tous les joueurs reçoivent deux cartes (la poche), puis cinq cartes sont distribuées à la table (les 3 premières sont appelées le flop, la suivante est le tournant et la dernière est la rivière.Chaque joueur choisit les cinq meilleures cartes pour constituer sa main.)

Si j'ai deux cartes dans la poche, P1 et P2, j'utiliserai les boucles suivantes pour générer toutes les combinaisons possibles :

for C1 := 0 to 51-4 do
  if (C1<>P1) and (C1<>P2) then
     for C2 := C1+1 to 51-3 do
       if (C2<>P1) and (C2<>P2) then
         for C3 := C2+1 to 51-2 do
           if (C3<>P1) and (C3<>P2) then
             for C4 := C3+1 to 51-1 do
               if (C4<>P1) and (C4<>P2) then
                 for C5 := C4+1 to 51 do
                   if (C5<>P1) and (C5<>P2) then
                   begin
                     //This code will be executed 2 118 760 times
                     inc(ComboCounter[GetComboFromCards([P1,P2,C1,C2,C3,C4,C5])]);
                   end;

En écrivant ceci, je remarque encore une chose :Les cinq derniers éléments du tableau seront toujours triés, il s'agit donc simplement de mettre les deux premiers éléments à la bonne position dans le tableau.Cela devrait simplifier un peu les choses.

La nouvelle question est donc :Quel est le moyen le plus rapide possible de trier un tableau de 7 entiers lorsque les 5 derniers éléments sont déjà triés.Je pense que cela pourrait être résolu avec quelques (?) de si et d'échanges :-)

Était-ce utile?

La solution

Je ne connais pas grand chose au Texas Hold'em: est-ce que les combinaisons P1 et P2 ont une importance, ou est-ce seulement si elles sont identiques ou non? Si seule la poursuite (P1) == la poursuite (P2) est importante, vous pouvez séparer les deux cas, vous n'avez que 13x12 / 2 possibilités différentes pour P1 / P2 et vous pouvez facilement précalculer une table pour les deux cas.

Sinon, je suggérerais quelque chose comme ceci:

(* C1 < C2 < P1 *)
for C1:=0 to P1-2 do 
   for C2:=C1+1 to P1-1 do 
      Cards[0] = C1;
      Cards[1] = C2;
      Cards[2] = P1;
      (* generate C3...C7 *)

(* C1 < P1 < C2 *)
for C1:=0 to P1-1 do 
   for C2:=P1+1 to 51 do 
      Cards[0] = C1;
      Cards[1] = P1;
      Cards[2] = C2;
      (* generate C3...C7 *)

(* P1 < C1 < C2 *)
for C1:=P1+1 to 51 do 
   for C2:=C1+1 to 51 do 
      Cards[0] = P1;
      Cards[1] = C1;
      Cards[2] = C2;
      (* generate C3...C7 *)

(ceci est juste une démonstration pour une carte P1, vous devriez développer cela pour P2, mais je pense que c'est simple. Même si ce sera beaucoup de dactylographie ...) De cette façon, le tri ne prend pas de temps du tout. Les permutations générées sont déjà commandées.

Autres conseils

Pour un très petit ensemble, le tri par insertion peut généralement battre quicksort car il a frais généraux très faibles.

WRT votre édition, si vous êtes déjà principalement dans l'ordre de tri (les 5 derniers éléments sont déjà triés), le tri par insertion est définitivement le chemin à parcourir. Dans un ensemble de données presque trié, il triomphe à chaque fois, même pour les grands ensembles. (Surtout pour les grands ensembles! Ceci est le meilleur des cas de tri par insertion et le pire des cas de tri rapide.)

Je ne sais pas comment vous l'implémentez, mais vous pouvez créer un tableau de 52 unités au lieu de 7 et insérer simplement la carte dans son emplacement directement lorsque vous l'obtenez, car il ne peut jamais y avoir de doublons. vous n'avez jamais à trier le tableau. Cela pourrait être plus rapide en fonction de l'utilisation qui en est faite.

Il n'y a que 5040 permutations de 7 éléments. Vous pouvez générer par programme un programme qui trouve celui représenté par votre entrée dans un nombre minimal de comparaisons. Ce sera un grand arbre d'instructions if-then-else, chacune comparant une paire fixe de nœuds, par exemple if (a[3]<=a[6]).

La partie délicate consiste à choisir les 2 éléments à comparer dans un nœud interne particulier. Pour cela, vous devez prendre en compte les résultats des comparaisons dans les nœuds ancêtres de la racine au nœud particulier (par exemple a[0]<=a[1], not a[2]<=a[7], a[2]<=a[5]) ainsi que l'ensemble des permutations possibles qui satisfont les comparaisons. Comparez la paire d'éléments qui divise l'ensemble en parties aussi égales que possible (minimisez la taille de la plus grande partie).

Une fois que vous avez obtenu la permutation, il est facile de la trier dans un ensemble minimal de swaps.

Les 5 derniers éléments étant déjà triés, le code peut être écrit uniquement pour repositionner les 2 premiers éléments. Depuis que vous utilisez Pascal, j'ai écrit et testé un algorithme de tri capable de s'exécuter 2 118 760 fois en environ 62 millisecondes.

procedure SortT7Cards(var Cards: T7Cards);
const
  CardsLength = Length(Cards);
var
  I, J, V: Integer;
  V1, V2: Integer;
begin
  // Last 5 items will always be sorted, so we want to place the first two into
  // the right location.
  V1 := Cards[0];
  V2 := Cards[1];
  if V2 < V1 then
  begin
    I := V1;
    V1 := V2;
    V2 := I;
  end;

  J := 0;
  I := 2;
  while I < CardsLength do
  begin
    V := Cards[I];
    if V1 < V then
    begin
      Cards[J] := V1;
      Inc(J);
      Break;
    end;
    Cards[J] := V;
    Inc(J);
    Inc(I);
  end;
  while I < CardsLength do
  begin
    V := Cards[I];
    if V2 < V then
    begin
      Cards[J] := V2;
      Break;
    end;
    Cards[J] := V;
    Inc(J);
    Inc(I);
  end;
  if J = (CardsLength - 2) then
  begin
    Cards[J] := V1;
    Cards[J + 1] := V2;
  end
  else if J = (CardsLength - 1) then
  begin
    Cards[J] := V2;
  end;
end;

Utilisez min-sort. Rechercher un élément minimal et maximal à la fois et les placer dans le tableau résultant. Répétez trois fois. (EDIT: Non, je ne vais pas essayer de mesurer la vitesse théoriquement: _))

var
cards,result: array[0..6] of integer;
i,min,max: integer;

begin
   n=0;
   while (n<3) do begin
      min:=-1;
      max:=52;
      for i from 0 to 6 do begin
          if cards[i]<min then min:=cards[i]
          else if cards[i]>max then max:=cards[i]
      end
      result[n]:=min;
      result[6-n]:=max;
      inc(n);
   end
   for i from 0 to 6 do 
       if (cards[i]<52) and (cards[i]>=0) then begin
           result[3] := cards[i];
           break;
       end
    { Result is sorted here! }
end

C’est la méthode la plus rapide: puisque la liste des 5 cartes est déjà triée, triez la liste des deux cartes (échangez &; échangez), puis fusionnez les deux listes, qui sont O (k * ( 5 + 2). Dans ce cas (k) sera normalement 5: le test de boucle (1), la comparaison (2), la copie (3), l’incrément de liste d’entrée (4) et l’incrément de liste de sortie (5 ). C’est 35 + 2. Initialisation de la boucle et vous obtenez 41,5 instructions, total.

Vous pouvez également dérouler les boucles, ce qui vous évitera peut-être 8 instructions ou exécutions, mais allongera la routine environ 4 à 5 fois plus longtemps, ce qui risquerait de gâcher le taux de réussite de la mémoire cache des instructions.

Soit P (0 à 2), C (0 à 5) et copie en H (0 à 6)  avec C () déjà trié (croissant):

If P(0) > P(1) Then
    // Swap:
    T = P(0)
    P(0) = P(1)
    P(1) = T
    // 1stmt + (3stmt * 50%) = 2.5stmt
End

P(2), C(5) = 53    \\ Note these are end-of-list flags
k = 0     \\ P() index
J = 0     \\ H() index
i = 0     \\ C() index
// 4 stmt

Do While (j) < 7 
    If P(k) < C(I) then
        H(j) = P(k)
        k = k+1
    Else
        H(j) = C(i)
        j = j+1
    End if
    j = j+1
    // 5stmt * 7loops = 35stmt
Loop

Et notez que c'est plus rapide que l'autre algorithme qui serait & "le plus rapide &"; si vous deviez vraiment trier les 7 cartes: utilisez un masque de bits (52) pour mapper & amp; placez les 7 cartes dans la plage de 52 cartes possibles (le masque de bits), puis balayez le masque de bits afin de rechercher les 7 bits définis. Cela prend au mieux 60 à 120 énoncés (mais reste plus rapide que toute autre méthode de tri).

Pour sept nombres, l'algorithme le plus efficace qui existe en ce qui concerne le nombre de comparaisons est celui de Ford-Johnson.En fait, Wikipédia fait référence à un article, facile à trouver sur Google, qui prétend que Ford-Johnson est le meilleur jusqu'à 47 chiffres.Malheureusement, les références à Ford-Johnson ne sont pas si faciles à trouver et l'algorithme utilise des structures de données complexes.

Il apparaît dans The Art Of Computer Programming, Volume 3, de Donald Knuth, si vous avez accès à ce livre.

Il existe un article qui décrit FJ et une version plus économe en mémoire ici.

Quoi qu'il en soit, en raison de la surcharge de mémoire de cet algorithme, je doute que cela en vaille la peine pour les entiers, car le coût de la comparaison de deux entiers est plutôt bon marché par rapport au coût de l'allocation de mémoire et de la manipulation des pointeurs.

Maintenant, vous avez mentionné que 5 cartes sont déjà triées et qu’il vous suffit d’en insérer deux.Vous pouvez le faire avec le tri par insertion le plus efficacement possible comme ceci :

Order the two cards so that P1 > P2
Insert P1 going from the high end to the low end
(list) Insert P2 going from after P1 to the low end
(array) Insert P2 going from the low end to the high end

La manière dont vous procéderez dépendra de la structure des données.Avec un tableau, vous échangerez chaque élément, alors placez P1 au 1er, P2 et 7ème (dans l'ordre de haut en bas), puis échangez P1 vers le haut, puis P2 vers le bas.Avec une liste, il vous suffit de corriger les pointeurs de manière appropriée.

Mais encore une fois, du fait de la particularité de votre code, il est préférable que vous suiviez Nikie suggestion et générez simplement les boucles for de manière appropriée pour chaque variation dans laquelle P1 et P2 peuvent apparaître dans la liste.

Par exemple, triez P1 et P2 de manière à ce que P1 < P2.Faisons de Po1 et Po2 la position de 0 à 6 de P1 et P2 sur la liste.Alors faites ceci :

Loop Po1 from 0 to 5
Loop Po2 from Po1 + 1 to 6
If (Po2 == 1) C1start := P2 + 1; C1end := 51 - 4
If (Po1 == 0 && Po2 == 2) C1start := P1+1; C1end := P2 - 1
If (Po1 == 0 && Po2 > 2) C1start := P1+1; C1end := 51 - 5
If (Po1 > 0) C1start := 0; C1end := 51 - 6
for C1 := C1start to C1end
  // Repeat logic to compute C2start and C2end
  // C2 can begin at C1+1, P1+1 or P2+1
  // C2 can finish at P1-1, P2-1, 51 - 3, 51 - 4 or 51 -5
  etc

Vous appelez ensuite une fonction passant Po1, Po2, P1, P2, C1, C2, C3, C4, C5, et demandez à cette fonction de renvoyer toutes les permutations possibles basées sur Po1 et Po2 (soit 36 ​​combinaisons).

Personnellement, je pense que c'est le plus rapide que l'on puisse obtenir.Vous évitez complètement de devoir commander quoi que ce soit, car les données seront précommandées.De toute façon, vous devez effectuer certaines comparaisons pour calculer les débuts et les fins, mais leur coût est minimisé car la plupart d'entre elles se trouveront sur les boucles les plus externes, elles ne seront donc pas beaucoup répétées.Et ils peuvent même être davantage optimisés au prix d’une plus grande duplication de code.

Pour 7 éléments, il n'y a que peu d'options. Vous pouvez facilement écrire un générateur qui produit une méthode pour trier toutes les combinaisons possibles de 7 éléments. Quelque chose comme cette méthode pour 3 éléments:

if a[1] < a[2] {
    if a[2] < a[3] {
        // nothing to do, a[1] < a[2] < a[3]
    } else {
         if a[1] < a[3] {
             // correct order should be a[1], a[3], a[2]
             swap a[2], a[3]
         } else {
             // correct order should be a[3], a[1], a[2]
             swap a[2], a[3]
             swap a[1], a[3]
         }
    }
} else {
    // here we know that a[1] >= a[2]
    ...
}

Bien sûr, la méthode pour 7 éléments sera plus grande, mais ce n’est pas si difficile à générer.

Le code ci-dessous est presque optimal. Cela pourrait être amélioré en composant une liste à parcourir en créant l'arbre, mais je n'ai plus de temps pour le moment. À la vôtre!

object Sort7 {
  def left(i: Int) = i * 4
  def right(i: Int) = i * 4 + 1
  def up(i: Int) = i * 4 + 2
  def value(i: Int) = i * 4 + 3

  val a = new Array[Int](7 * 4)
  def reset = {
    0 until 7 foreach { 
      i => {
        a(left(i)) = -1
        a(right(i)) = -1
        a(up(i)) = -1
        a(value(i)) = scala.util.Random.nextInt(52)
      }
    }
  }

  def sortN(i : Int) {
    var index = 0
    def getNext = if (a(value(i)) < a(value(index))) left(index) else right(index)
    var next = getNext
    while(a(next) != -1) {
      index = a(next)
      next = getNext
    }
    a(next) = i
    a(up(i)) = index
  }

  def sort = 1 until 7 foreach (sortN(_))

  def print {
    traverse(0)
    def traverse(i: Int): Unit = {
      if (i != -1) {
        traverse(a(left(i)))
        println(a(value(i)))
        traverse(a(right(i)))
      }
    }
  }
}

En pseudo-code:

int64 temp = 0;
int index, bit_position;

for index := 0 to 6 do
   temp |= 1 << cards[index];

for index := 0 to 6 do
begin
   bit_position = find_first_set(temp);
   temp &= ~(1 << bit_position);
   cards[index] = bit_position;
end;

Il s'agit d'une application du tri par seau , qui devrait généralement être plus rapide que la comparaison sortes qui ont été suggérées.

Remarque: La deuxième partie pourrait également être implémentée en effectuant une itération sur des bits dans le temps linéaire, mais en pratique, elle risque de ne pas être plus rapide:

index = 0;
for bit_position := 0 to 51 do
begin
   if (temp & (1 << bit_position)) > 0 then
   begin
      cards[index] = bit_position;
      index++;
   end;
end;

En supposant que vous ayez besoin d'un tableau de cartes à la fin.

Mappez les cartes originales en bits dans un entier de 64 bits (ou tout autre entier avec > = 52 bits).

Si, lors du mappage initial, le tableau est trié, ne le changez pas.

Partitionnez le nombre entier en petits octets - chacun correspondra aux valeurs 0x0 à 0xf.

Utilisez les octets en tant qu’index pour les sous-tableaux triés correspondants. Vous aurez besoin de 13 ensembles de 16 sous-tableaux (ou tout simplement de 16 sous-tableaux et utilisez une seconde indirection, ou effectuez les opérations sur les bits plutôt que de rechercher la réponse; ce qui est plus rapide varie en fonction de la plate-forme).

Concaténez les sous-tableaux non vides dans le tableau final.

Vous pouvez utiliser plus que des grignotines si vous le souhaitez. octets donnerait 7 ensembles de 256 tableaux et augmenterait la probabilité que les tableaux non vides nécessitent une concaténation.

Cela suppose que les branches sont chères et que les accès au tableau mis en cache sont bon marché.

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>

// for general case of 7 from 52, rather than assuming last 5 sorted
uint32_t card_masks[16][5] = {
    { 0, 0, 0, 0, 0 },
    { 1, 0, 0, 0, 0 },
    { 2, 0, 0, 0, 0 },
    { 1, 2, 0, 0, 0 },
    { 3, 0, 0, 0, 0 },
    { 1, 3, 0, 0, 0 },
    { 2, 3, 0, 0, 0 },
    { 1, 2, 3, 0, 0 },
    { 4, 0, 0, 0, 0 },
    { 1, 4, 0, 0, 0 },
    { 2, 4, 0, 0, 0 },
    { 1, 2, 4, 0, 0 },
    { 3, 4, 0, 0, 0 },
    { 1, 3, 4, 0, 0 },
    { 2, 3, 4, 0, 0 },
    { 1, 2, 3, 4, 0 },
};

void sort7 ( uint32_t* cards) {
    uint64_t bitset = ( ( 1LL << cards[ 0 ] ) | ( 1LL << cards[ 1LL ] ) | ( 1LL << cards[ 2 ] ) | ( 1LL << cards[ 3 ] ) | ( 1LL << cards[ 4 ] ) | ( 1LL << cards[ 5 ] ) | ( 1LL << cards[ 6 ] ) ) >> 1;

    uint32_t*   p    = cards;
    uint32_t    base = 0;

    do {
        uint32_t* card_mask = card_masks[ bitset & 0xf ];

        // you might remove this test somehow, as well as unrolling the outer loop
        // having separate arrays for each nibble would save 7 additions and the increment of base
        while ( *card_mask )
            *(p++) = base + *(card_mask++);

        bitset >>= 4;
        base += 4;
    } while ( bitset );
}

void print_cards ( uint32_t* cards ) {
    printf ( "[ %d %d %d %d %d %d %d ]\n", cards[0], cards[1], cards[2], cards[3], cards[4], cards[5], cards[6] );
}

int main ( void ) {
    uint32_t cards[7] = { 3, 9, 23, 17, 2, 42, 52 };

    print_cards ( cards );
    sort7 ( cards );
    print_cards ( cards );

    return 0;
}

Regardez ceci:

http://en.wikipedia.org/wiki/Sorting_algorithm

Vous devez en choisir un qui aura un coût stable dans le pire des cas ...

Une autre option pourrait être de garder le tableau trié tout le temps, de sorte qu'un ajout de carte maintiendrait le tableau trié automatiquement, afin que vous puissiez passer au tri ...

JRL fait référence à un type de seau. Puisque vous avez un ensemble discret fini de valeurs possibles, vous pouvez déclarer 52 compartiments et simplement déposer chaque élément dans un compartiment en un temps O (1). Par conséquent, le type de seau est O (n). Sans la garantie d'un nombre fini d'éléments différents, le tri théorique le plus rapide est O (n log n), ce que sont, par exemple, le tri par fusion et par tri rapide. Il s’agit alors d’un juste équilibre entre les meilleurs et les pires scénarios.

Mais réponse courte, utilisez le tri par seau.

Si vous aimez la suggestion ci-dessus de conserver un tableau de 52 éléments qui garde toujours votre tableau trié, vous pouvez peut-être conserver une autre liste de 7 éléments référençant les 7 éléments valides du tableau de 52 éléments. De cette façon, nous pouvons même éviter d'analyser le tableau de 52 éléments.

Je suppose que pour que cela soit vraiment efficace, nous aurions besoin d'une structure de type liste liée qui supporte les opérations: InsertAtPosition () et DeleteAtPosition () et soit efficace à cet égard.

Il y a beaucoup de boucles dans les réponses. Compte tenu de sa vitesse et de la taille réduite de l'ensemble de données, je ne ferais AUCUNE boucle.

Je n’ai pas essayé, mais je soupçonne que la meilleure réponse est une sorte de bulle entièrement déroulée. Cela aurait aussi probablement l'avantage de se faire en assemblée.

Je me demande toutefois si cette approche est la bonne. Comment allez-vous analyser une main de 7 cartes? De toute façon, je pense que vous allez finir par le convertir en une autre représentation pour analyse. Un tableau 4x13 ne serait-il pas une représentation plus utile? (Et cela rendrait le problème de tri sans intérêt, de toute façon.)

Considérant que les 5 derniers éléments sont toujours triés:


for i := 0 to 1 do begin
  j := i;
  x := array[j];
  while (j+1 <= 6) and (array[j+1] < x) do begin
    array[j] := array[j+1];
    inc(j);
  end;
  array[j] := X;
end;

type de bulle est votre ami. D'autres types ont trop de codes généraux et ne conviennent pas à un petit nombre d'éléments

A bientôt

Voici votre type de base O (n). Je ne suis pas sûr de savoir comment cela se compare aux autres. Il utilise des boucles déroulées.

char card[7]; // the original table of 7 numbers in range 0..51
char table[52]; // workspace

// clear the workspace
memset(table, 0, sizeof(table));

// set the 7 bits corresponding to the 7 cards
table[card[0]] = 1;
table[card[1]] = 1;
...
table[card[6]] = 1;

// read the cards back out
int j = 0;
if (table[0]) card[j++] = 0;
if (table[1]) card[j++] = 1;
...
if (table[51]) card[j++] = 51;

Si vous recherchez un tri optimal, vous devez créer un réseau de tri. Vous pouvez générer le code d'un réseau de 7 nombres entiers à l'aide de l'algorithme Bose-Nelson.

Cela garantirait un nombre fixe de comparaisons et un nombre égal de swaps dans le pire des cas.

Le code généré est moche, mais il est optimal.

Vos données sont dans un tableau trié et je supposerai que vous permutez les deux nouveaux si nécessaire, donc aussi triés, donc une. si vous voulez le garder en place, utilisez une forme de tri par insertion; b. si vous voulez avoir le résultat dans un autre tableau, faites une fusion en copiant.

Avec les petits nombres, le hachage binaire est excessif, et le hachage ternaire est quand même approprié: Une nouvelle carte sera la plupart du temps comme divisée en deux et trois, à savoir. 2 + 3 ou 3 + 2, deux cartes en simples et en paires, par ex. 2 + 1 + 2.

L’approche la plus efficace en termes de gain de temps et d’espace pour placer la nouvelle carte plus petite consiste à comparer avec un [1] (à savoir, ignorer un [0]), puis de rechercher à gauche ou à droite la carte qu’elle doit déplacer, puis de la permuter. et déplacez-vous vers la droite (décalage plutôt que de faire des bulles), en comparant avec la nouvelle carte plus grande jusqu'à ce que vous trouviez où elle va. Après cela, vous passerez deux par deux (deux cartes ont été insérées). Les variables contenant les nouvelles cartes (et swaps) doivent être des registres.

L'approche de recherche serait plus rapide mais utiliserait plus de mémoire.

Utilisez un réseau de tri, comme dans ce code C ++:

template<class T> 
inline void sort7(T data) {
#define SORT2(x,y) {if(data##x>data##y)std::swap(data##x,data##y);}
//DD = Define Data, create a local copy of the data to aid the optimizer.
#define DD1(a)   register auto data##a=*(data+a);
#define DD2(a,b) register auto data##a=*(data+a);register auto data##b=*(data+b);
//CB = Copy Back
#define CB1(a)   *(data+a)=data##a;
#define CB2(a,b) *(data+a)=data##a;*(data+b)=data##b;
  DD2(1,2) SORT2(1,2)
  DD2(3,4) SORT2(3,4)
  DD2(5,6) SORT2(5,6)
  DD1(0) SORT2(0,2)
  SORT2(3,5) 
  SORT2(4,6) 
  SORT2(0,1)
  SORT2(4,5) 
  SORT2(2,6) CB1(6)
  SORT2(0,4) 
  SORT2(1,5)
  SORT2(0,3) CB1(0) 
  SORT2(2,5) CB1(5)
  SORT2(1,3) CB1(1) 
  SORT2(2,4) CB1(4)
  SORT2(2,3) CB2(2,3)
#undef CB1
#undef CB2
#undef DD1
#undef DD2
#undef SORT2
}

Utilisez la fonction ci-dessus si vous souhaitez lui attribuer un itérateur ou un pointeur et utilisez la fonction ci-dessous si vous souhaitez lui transmettre les sept arguments un par un. BTW, en utilisant des modèles, permet aux compilateurs de générer un code vraiment optimisé. Ne vous laissez pas guider par le template<> sauf si vous voulez le code C (ou le code d’une autre langue).

template<class T>
inline void sort7(T& e0, T& e1, T& e2, T& e3, T& e4, T& e5, T& e6) {
#define SORT2(x,y) {if(data##x>data##y)std::swap(data##x,data##y);}
#define DD1(a)   register auto data##a=e##a;
#define DD2(a,b) register auto data##a=e##a;register auto data##b=e##b;
#define CB1(a)   e##a=data##a;
#define CB2(a,b) e##a=data##a;e##b=data##b;
  DD2(1,2) SORT2(1,2)
  DD2(3,4) SORT2(3,4)
  DD2(5,6) SORT2(5,6)
  DD1(0) SORT2(0,2)
  SORT2(3,5)
  SORT2(4,6)
  SORT2(0,1)
  SORT2(4,5)
  SORT2(2,6) CB1(6)
  SORT2(0,4)
  SORT2(1,5)
  SORT2(0,3) CB1(0)
  SORT2(2,5) CB1(5)
  SORT2(1,3) CB1(1)
  SORT2(2,4) CB1(4)
  SORT2(2,3) CB2(2,3)
#undef CB1
#undef CB2
#undef DD1
#undef DD2
#undef SORT2
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top