Domanda

Questa è una parte di un programma che analizza le probabilità del poker, in particolare del Texas Hold'em.Ho un programma di cui sono soddisfatto, ma necessita di alcune piccole ottimizzazioni per essere perfetto.

Io uso questo tipo (tra gli altri, ovviamente):

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

Ci sono due cose su questo array che potrebbero essere importanti quando si decide come ordinarlo:

  1. Ogni elemento ha un valore compreso tra 0 e 51.Nessun altro valore è possibile.
  2. Non ci sono duplicati.Mai.

Con queste informazioni, qual è il assolutamente più veloce modo per ordinare questo array?Uso Delphi, quindi il codice pascal sarebbe il migliore, ma so leggere C e pseudo, anche se un po' più lentamente :-)

Al momento utilizzo Quicksort, ma la cosa divertente è che non è quasi più veloce di Bubblesort!Possibile a causa del numero limitato di articoli.L'ordinamento conta per quasi il 50% del tempo di esecuzione totale del metodo.

MODIFICARE:

Mason Wheeler ha chiesto perché è necessario ottimizzare.Uno dei motivi è che il metodo verrà chiamato 2118760 volte.

Informazioni di base sul poker:A tutti i giocatori vengono distribuite due carte (la pocket) e poi vengono distribuite sul tavolo cinque carte (le prime 3 sono chiamate flop, la successiva è il turn e l'ultima è il river).Ogni giocatore sceglie le cinque carte migliori per comporre la propria mano)

Se ho due carte in tasca, P1 e P2, utilizzerò i seguenti cicli per generare tutte le possibili combinazioni:

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;

Mentre scrivo mi accorgo di un'altra cosa:Gli ultimi cinque elementi dell'array verranno sempre ordinati, quindi è solo questione di mettere i primi due elementi nella giusta posizione nell'array.Questo dovrebbe semplificare un po' le cose.

Quindi la nuova domanda è:Qual è il modo più veloce possibile per ordinare un array di 7 numeri interi quando gli ultimi 5 elementi sono già ordinati.Credo che questo potrebbe essere risolto con un paio (?) di if e swap :-)

È stato utile?

Soluzione

Non so molto del Texas Hold'em: importa quale seme P1 e P2 sono, o importa solo se sono dello stesso seme o no? Se solo seme (P1) == seme (P2) è importante, puoi separare i due casi, hai solo 13x12 / 2 possibilità diverse per P1 / P2 e puoi facilmente precalcolare una tabella per i due casi.

Altrimenti, suggerirei qualcosa del genere:

(* 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 *)

(questa è solo una dimostrazione per una scheda P1, dovresti espanderla per P2, ma penso che sia semplice. Anche se sarà un sacco di scrivere ...) In questo modo, l'ordinamento non richiede affatto tempo. Le permutazioni generate sono già ordinate.

Altri suggerimenti

Per un set molto piccolo, ordinamento per inserzione di solito può battere quicksort perché ha spese generali molto basse.

WRT la tua modifica, se sei già principalmente nell'ordinamento (gli ultimi 5 elementi sono già ordinati), l'ordinamento per inserzione è sicuramente la strada da percorrere. In una serie quasi ordinata di dati, batterà quicksort ogni volta, anche per serie grandi. (Soprattutto per set di grandi dimensioni! Questo è lo scenario migliore per inserzione e il peggiore per quicksort.)

Non so come lo stai implementando, ma quello che potresti fare è avere un array di 52 invece di 7, e basta inserire la scheda nel suo slot direttamente quando la ottieni poiché non ci possono mai essere duplicati, in quel modo non devi mai ordinare l'array. Questo potrebbe essere più veloce a seconda di come è stato utilizzato.

Esistono solo 5040 permutazioni di 7 elementi.Puoi generare a livello di codice un programma che trova quello rappresentato dal tuo input in un numero minimo di confronti.Sarà un grande albero di if-then-else istruzioni, ciascuna delle quali confronta una coppia fissa di nodi, ad esempio if (a[3]<=a[6]).

La parte difficile è decidere quali 2 elementi confrontare in un particolare nodo interno.Per questo, devi prendere in considerazione i risultati dei confronti nei nodi antenati dalla radice al nodo particolare (ad esempio a[0]<=a[1], not a[2]<=a[7], a[2]<=a[5]) e l'insieme delle possibili permutazioni che soddisfano i confronti.Confronta la coppia di elementi che divide l'insieme in parti quanto più uguali possibile (riduci al minimo la dimensione della parte più grande).

Una volta ottenuta la permutazione, è banale ordinarla in un insieme minimo di scambi.

Poiché gli ultimi 5 elementi sono già ordinati, il codice può essere scritto solo per riposizionare i primi 2 elementi. Da quando usi Pascal, ho scritto e testato un algoritmo di ordinamento che può essere eseguito 2.118.760 volte in circa 62 millisecondi.

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;

Usa min-sort. Cerca subito l'elemento minimo e massimo e inseriscili nell'array risultante. Ripeti tre volte. (EDIT: No, non proverò a misurare la velocità teoricamente: _))

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

Questo è il metodo più veloce: poiché l'elenco di 5 carte è già ordinato, ordina l'elenco di due carte (un confronto & amp; swap), quindi unisci le due liste, che è O (k * ( 5 + 2) In questo caso (k) saranno normalmente 5: il loop test (1), il confronto (2), la copia (3), l'incremento dell'elenco di input (4) e l'incremento dell'elenco di output (5) Sono 35 + 2.5. Lancia l'inizializzazione in loop e ottieni 41,5 istruzioni, in totale.

Potresti anche srotolare i loop che potrebbero farti risparmiare forse 8 istruzioni o esecuzioni, ma rendere l'intera routine circa 4-5 volte più lunga che potrebbe interferire con il rapporto di risultati della cache delle istruzioni.

Dato P (da 0 a 2), C (da 0 a 5) e copia in H (da 0 a 6)  con C () già ordinato (crescente):

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

E nota che questo è più veloce dell'altro algoritmo che sarebbe " il più veloce " se dovessi ordinare veramente tutte e 7 le carte: usa una maschera di bit (52) per mappare l'amplificatore &; metti tutte le 7 carte in quell'intervallo di tutte le 52 carte possibili (la maschera di bit), quindi scansiona la maschera di bit in modo da cercare i 7 bit impostati. Ciò richiede nella migliore delle ipotesi 60-120 (ma è ancora più veloce di qualsiasi altro approccio all'ordinamento).

Per sette numeri, l'algoritmo più efficiente esistente per quanto riguarda il numero di confronti è quello di Ford-Johnson. In effetti, wikipedia fa riferimento a un documento, facilmente reperibile su google, che afferma che Ford-Johnson è il migliore per un massimo di 47 numeri. Sfortunatamente, i riferimenti a Ford-Johnson non sono così facili da trovare e l'algoritmo utilizza alcune strutture di dati complesse.

Appare su The Art Of Computer Programming, Volume 3, di Donald Knuth, se hai accesso a quel libro.

C'è un documento che descrive FJ e una versione più efficiente della memoria qui .

Ad ogni modo, a causa del sovraccarico di memoria di quell'algoritmo, dubito che varrebbe la pena per gli interi, poiché il costo del confronto di due interi è piuttosto economico rispetto al costo dell'allocazione della memoria e della manipolazione dei puntatori.

Ora, hai detto che 5 carte sono già state ordinate e devi solo inserirne due. Puoi farlo con l'ordinamento per inserzione in modo più efficiente in questo modo:

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

Il modo in cui lo fai dipenderà dalla struttura dei dati. Con un array scambierete ogni elemento, quindi posizionate P1 al 1 °, P2 e 7 ° (dal più alto al più basso), quindi scambiate P1 in alto, quindi P2 in basso. Con un elenco, devi solo correggere i puntatori come appropriato.

Tuttavia, ancora una volta, a causa della particolarità del tuo codice, è davvero meglio seguire il suggerimento nikie e solo genera i cicli for in modo appropriato per ogni variazione in cui P1 e P2 possono apparire nell'elenco.

Ad esempio, ordina P1 e P2 in modo che P1 < P2. Facciamo Po1 e Po2 la posizione da 0 a 6, di P1 e P2 nell'elenco. Quindi fai questo:

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

Chiamate quindi una funzione che passa Po1, Po2, P1, P2, C1, C2, C3, C4, C5 e questa funzione restituisce tutte le possibili permutazioni basate su Po1 e Po2 (ovvero 36 combinazioni).

Personalmente, penso che sia il più veloce che puoi ottenere. Eviti completamente di dover ordinare qualsiasi cosa, perché i dati verranno preordinati. In alcuni confronti si incorre in alcuni confronti per calcolare l'inizio e la fine, ma il loro costo è ridotto al minimo in quanto la maggior parte di essi si troverà sui circuiti più esterni, quindi non si ripeteranno molto. E possono anche essere più ottimizzati al costo di una maggiore duplicazione del codice.

Per 7 elementi, ci sono solo poche opzioni. Puoi facilmente scrivere un generatore che produce metodo per ordinare tutte le possibili combinazioni di 7 elementi. Qualcosa di simile a questo metodo per 3 elementi:

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]
    ...
}

Naturalmente il metodo per 7 elementi sarà più grande, ma non è così difficile da generare.

Il codice seguente è quasi ottimale. Potrebbe essere migliorato componendo un elenco da attraversare mentre si fa l'albero, ma al momento sono fuori tempo. Cheers!

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)))
      }
    }
  }
}

In pseudo codice:

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;

È un'applicazione di bucket bucket , che dovrebbe essere generalmente più veloce di qualsiasi confronto tipi che sono stati suggeriti.

Nota: la seconda parte potrebbe anche essere implementata ripetendo i bit in tempo lineare, ma in pratica potrebbe non essere più veloce:

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;

Supponendo che alla fine sia necessario un array di carte.

Mappa le carte originali in bit in un numero intero a 64 bit (o qualsiasi numero intero con > = 52 bit).

Se durante la mappatura iniziale l'array viene ordinato, non modificarlo.

Partiziona l'intero in stuzzichini - ognuno corrisponderà ai valori da 0x0 a 0xf.

Usa i nibble come indici per i corrispondenti sotto-array ordinati. Avrai bisogno di 13 serie di 16 sotto-array (o solo 16 sotto-array e usano una seconda indiretta, oppure esegui le operazioni bit invece di cercare la risposta; ciò che è più veloce varierà a seconda della piattaforma).

Concatena i sotto-array non vuoti nell'array finale.

Se lo desideri, puoi usare più di stuzzichini; i byte darebbero 7 serie di 256 matrici e renderebbero più probabile che le matrici non vuote richiedano la concatenazione.

Ciò presuppone che i rami siano costosi e che gli accessi alla matrice memorizzati nella cache siano economici.

#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;
}

Dai un'occhiata a questo:

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

Dovresti sceglierne uno che avrà un costo nel caso peggiore stabile ...

Un'altra opzione potrebbe essere quella di mantenere l'array ordinato tutto il tempo, quindi un'aggiunta di una carta manterrà l'array ordinato automaticamente, in questo modo potresti saltare all'ordinamento ...

Ciò a cui JRL si riferisce è un ordinamento bucket. Dato che hai un insieme discreto finito di possibili valori, puoi dichiarare 52 secchi e rilasciare ogni elemento in un bucket in O (1) volta. Quindi l'ordinamento bucket è O (n). Senza la garanzia di un numero finito di elementi diversi, l'ordinamento teorico più veloce è O (n log n) quali sono le cose come unire un ordinamento veloce. Quindi è solo un equilibrio tra gli scenari migliori e peggiori.

Ma lunga risposta breve, usa l'ordinamento bucket.

Se ti piace il suggerimento sopra menzionato di mantenere una matrice di 52 elementi che mantiene sempre ordinata la tua matrice, allora potresti essere in grado di mantenere un altro elenco di 7 elementi che farebbero riferimento ai 7 elementi validi nella matrice di 52 elementi. In questo modo possiamo persino evitare di analizzare l'array di 52 elementi.

Immagino che questo sia davvero efficiente, avremmo bisogno di un tipo di struttura di elenco collegato che supporti le operazioni: InsertAtPosition () e DeleteAtPosition () ed essere efficiente in questo.

Ci sono molti loop nelle risposte. Dati i suoi requisiti di velocità e le minuscole dimensioni del set di dati, non farei QUALSIASI loop.

Non l'ho provato ma sospetto che la risposta migliore sia una sorta di bolla completamente srotolata. Probabilmente otterrebbe anche un discreto vantaggio dall'assemblaggio.

Mi chiedo però se questo è l'approccio giusto. Come hai intenzione di analizzare una mano di 7 carte ?? Penso che finirai per convertirlo in qualche altra rappresentazione per l'analisi comunque. Un array 4x13 non sarebbe una rappresentazione più utile? (E renderebbe comunque discutibile il problema dell'ordinamento.)

Considerando che gli ultimi 5 elementi sono sempre ordinati:


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;

bubble sort è tuo amico. Altri tipi hanno troppi codici generali e non sono adatti per un numero limitato di elementi

Saluti

Ecco il tuo ordinamento O (n) di base. Non sono sicuro di come si confronta con gli altri. Utilizza loop non srotolati.

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;

Se stai cercando un overhead molto basso, un ordinamento ottimale, dovresti creare una rete di smistamento. Puoi generare il codice per una rete a 7 numeri interi usando l'algoritmo Bose-Nelson.

Ciò garantirebbe un numero fisso di confronti e un numero uguale di swap nel caso peggiore.

Il codice generato è brutto, ma è ottimale.

I tuoi dati sono in un array ordinato e suppongo che tu cambi i nuovi due, se necessario, così anche ordinati, quindi un. se si desidera mantenerlo in posizione, utilizzare una forma di ordinamento per inserimento; b. se vuoi averlo il risultato in un altro array fai una fusione copiando.

Con i numeri piccoli, il taglio binario è eccessivo e il taglio ternario è appropriato comunque: Una nuova carta piacerà per lo più divisa in due e tre, vale a dire. 2 + 3 o 3 + 2, due carte in singoli e coppie, ad es. 2 + 1 + 2.

Quindi l'approccio più efficiente in termini di spazio-tempo per posizionare la nuova carta più piccola è confrontarsi con un [1] (vale a dire saltare un [0]) e quindi cercare a sinistra oa destra per trovare la carta che dovrebbe spostare, quindi scambiare e muoviti a destra (spostando anziché gorgogliare), confrontandoti con la nuova carta più grande fino a trovare dove va. Dopo questo ti sposterai in avanti di due (sono state inserite due carte). Le variabili che contengono le nuove carte (e gli swap) dovrebbero essere registri.

L'approccio di ricerca sarebbe più veloce ma usa più memoria.

Utilizza una rete di ordinamento, come in questo codice 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
}

Utilizzare la funzione sopra se si desidera passare un iteratore o un puntatore e utilizzare la funzione di seguito se si desidera passare i sette argomenti uno per uno. A proposito, l'uso di modelli consente ai compilatori di generare codice davvero ottimizzato, quindi non andare oltre il template<> a meno che tu non voglia il codice C (o un codice di qualche altra lingua).

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
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top