Pregunta

Esta es una parte de un programa que analiza las probabilidades de póker, específicamente Texas Hold'em. Tengo un programa con el que estoy contento, pero necesita algunas pequeñas optimizaciones para ser perfecto.

Uso este tipo (entre otros, por supuesto):

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

Hay dos cosas acerca de esta matriz que pueden ser importantes al decidir cómo ordenarla:

  1. Cada elemento es un valor de 0 a 51. No hay otros valores posibles.
  2. No hay duplicados. Nunca.

Con esta información, ¿cuál es la forma absolutamente más rápida de ordenar esta matriz? Uso Delphi, por lo que el código pascal sería el mejor, pero puedo leer C y pseudo, aunque un poco más lentamente :-)

En este momento uso quicksort, ¡pero lo curioso es que esto no es casi más rápido que el bubbleort! Posible debido a la pequeña cantidad de artículos. La clasificación representa casi el 50% del tiempo total de ejecución del método.

EDITAR:

Mason Wheeler preguntó por qué es necesario optimizar. Una razón es que el método se llamará 2118760 veces.

Información básica del póker: a todos los jugadores se les reparten dos cartas (el bolsillo) y luego cinco cartas a la mesa (las 3 primeras se llaman flop, la siguiente es el turno y la última es el river. Cada jugador elige las cinco mejores cartas para formar su mano)

Si tengo dos cartas en el bolsillo, P1 y P2, usaré los siguientes bucles para generar todas las combinaciones posibles:

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;

Mientras escribo esto, noto una cosa más: los últimos cinco elementos de la matriz siempre se ordenarán, por lo que es solo una cuestión de colocar los dos primeros elementos en la posición correcta en la matriz. Eso debería simplificar un poco las cosas.

Entonces, la nueva pregunta es: ¿Cuál es la forma más rápida posible de ordenar una matriz de 7 enteros cuando los últimos 5 elementos ya están ordenados? Creo que esto podría resolverse con un par (?) De if's y swaps :-)

¿Fue útil?

Solución

No sé mucho sobre Texas Hold'em: ¿Importa qué traje son P1 y P2, o solo importa si son del mismo palo o no? Si solo importa el palo (P1) == palo (P2), entonces podría separar los dos casos, tiene solo 13x12 / 2 posibilidades diferentes para P1 / P2, y puede precalcular fácilmente una tabla para los dos casos.

De lo contrario, sugeriría algo como esto:

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

(esto es solo una demostración para una tarjeta P1, tendrías que ampliar eso para P2, pero creo que es sencillo. Aunque será mucho escribir ...) De esa manera, la clasificación no toma tiempo en absoluto. Las permutaciones generadas ya están ordenadas.

Otros consejos

Para un conjunto muy pequeño, tipo de inserción generalmente puede vencer a quicksort porque tiene muy poca sobrecarga.

ESCRIBA su edición, si ya está principalmente en orden de clasificación (los últimos 5 elementos ya están ordenados), la clasificación por inserción es definitivamente el camino a seguir. En un conjunto de datos casi ordenado, siempre superará la clasificación rápida, incluso para conjuntos grandes. (¡Especialmente para conjuntos grandes! Este es el mejor de los casos de inserción y el peor de los de quicksort).

No sé cómo está implementando esto, pero lo que podría hacer es tener una matriz de 52 en lugar de 7, e simplemente inserte la tarjeta en su ranura directamente cuando la obtenga, ya que nunca puede haber duplicados, de esa manera nunca tienes que ordenar la matriz. Esto podría ser más rápido dependiendo de cómo se use.

Solo hay 5040 permutaciones de 7 elementos. Puede generar programáticamente un programa que encuentre el representado por su entrada en un número mínimo de comparaciones. Será un gran árbol de if-then-else instrucciones, cada una comparando un par fijo de nodos, por ejemplo if (a[3]<=a[6]).

La parte difícil es decidir qué 2 elementos comparar en un nodo interno particular. Para esto, debe tener en cuenta los resultados de las comparaciones en los nodos ancestrales desde la raíz hasta el nodo particular (por ejemplo, a[0]<=a[1], not a[2]<=a[7], a[2]<=a[5]) y el conjunto de posibles permutaciones que satisfacen las comparaciones. Compare el par de elementos que divide el conjunto en partes tan iguales como sea posible (minimice el tamaño de la parte más grande).

Una vez que tenga la permutación, es trivial clasificarla en un conjunto mínimo de intercambios.

Dado que los últimos 5 elementos ya están ordenados, el código se puede escribir solo para reposicionar los primeros 2 elementos. Como está usando Pascal, he escrito y probado un algoritmo de clasificación que puede ejecutarse 2,118,760 veces en aproximadamente 62 milisegundos.

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;

Use min-sort. Busque elementos mínimos y máximos a la vez y colóquelos en la matriz resultante. Repite tres veces. (EDITAR: No, no intentaré medir la velocidad teóricamente: _))

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

Este es el método más rápido: dado que la lista de 5 cartas ya está ordenada, clasifique la lista de dos cartas (una comparación & amp; swap), y luego combine las dos listas, que es O (k * ( 5 + 2). En este caso (k) normalmente será 5: la prueba de bucle (1), la comparación (2), la copia (3), el incremento de la lista de entrada (4) y el incremento de la lista de salida (5 ). Eso es 35 + 2.5. Agregue la inicialización del ciclo y obtendrá 41.5 declaraciones, en total.

También podría desenrollar los bucles, lo que le ahorraría quizás 8 sentencias o ejecuciones, pero haga que la rutina completa sea aproximadamente 4-5 veces más larga, lo que puede afectar su índice de aciertos de caché de instrucciones.

Dado P (0 a 2), C (0 a 5) y copiando a H (0 a 6)  con C () ya ordenado (ascendente):

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

Y tenga en cuenta que esto es más rápido que el otro algoritmo que sería & "; más rápido &"; si realmente tuviera que ordenar las 7 cartas: use una máscara de bits (52) para mapear & amp; configure las 7 tarjetas en ese rango de todas las 52 tarjetas posibles (la máscara de bits), y luego escanee la máscara de bits para buscar los 7 bits que están configurados. Eso toma 60-120 declaraciones en el mejor de los casos (pero sigue siendo más rápido que cualquier otro enfoque de clasificación).

Para siete números, el algoritmo más eficiente que existe con respecto al número de comparaciones es el de Ford-Johnson. De hecho, wikipedia hace referencia a un artículo, que se encuentra fácilmente en Google, que afirma que Ford-Johnson es el mejor para hasta 47 números. Desafortunadamente, las referencias a Ford-Johnson no son tan fáciles de encontrar, y el algoritmo usa algunas estructuras de datos complejas.

Aparece en The Art Of Computer Programming, Volume 3, de Donald Knuth, si tiene acceso a ese libro.

Hay un documento que describe FJ y una versión más eficiente en memoria aquí .

En cualquier caso, debido a la sobrecarga de memoria de ese algoritmo, dudo que valga la pena para los enteros, ya que el costo de comparar dos enteros es bastante barato en comparación con el costo de asignar memoria y manipular punteros.

Ahora, mencionó que 5 tarjetas ya están ordenadas, y solo necesita insertar dos. Puede hacer esto con el tipo de inserción de la manera más eficiente como se muestra a continuación:

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

Cómo lo haga dependerá de la estructura de datos. Con una matriz, intercambiarás cada elemento, así que coloca P1 en 1er, P2 y 7 ° (ordenado de mayor a menor), y luego intercambia P1 hacia arriba y luego P2 hacia abajo. Con una lista, solo necesita corregir los punteros según corresponda.

Sin embargo, una vez más, debido a la particularidad de su código, realmente es mejor si sigue la sugerencia nikie y solo generar los bucles for de forma adecuada para cada variación en la que P1 y P2 pueden aparecer en la lista.

Por ejemplo, clasifique P1 y P2 para que P1 < P2 Hagamos de Po1 y Po2 la posición de 0 a 6, de P1 y P2 en la lista. Luego haz esto:

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

Luego llama a una función que pasa Po1, Po2, P1, P2, C1, C2, C3, C4, C5, y hace que esta función devuelva todas las permutaciones posibles basadas en Po1 y Po2 (eso es 36 combinaciones).

Personalmente, creo que es lo más rápido que puedes conseguir. Evita por completo tener que pedir nada, porque los datos se preordenarán. De todos modos, realiza algunas comparaciones para calcular los comienzos y los finales, pero su costo se minimiza ya que la mayoría de ellos estarán en los bucles más externos, por lo que no se repetirán mucho. E incluso se pueden optimizar más a costa de una mayor duplicación de código.

Para 7 elementos, solo hay algunas opciones. Puede escribir fácilmente un generador que produzca un método para ordenar todas las combinaciones posibles de 7 elementos. Algo así como este método para 3 elementos:

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

Por supuesto, el método para 7 elementos será más grande, pero no es tan difícil de generar.

El siguiente código es casi óptimo. Podría mejorarse componiendo una lista para recorrer mientras se hace el árbol, pero ahora no tengo tiempo. ¡Saludos!

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 pseudocódigo:

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;

Es una aplicación de tipo de cubo , que generalmente debería ser más rápido que cualquiera de la comparación tipos sugeridos.

Nota: La segunda parte también podría implementarse iterando sobre bits en tiempo lineal, pero en la práctica puede no ser más rápido:

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;

Suponiendo que necesita una serie de tarjetas al final de la misma.

Asigna las tarjetas originales a bits en un entero de 64 bits (o cualquier entero con > = 52 bits).

Si durante la asignación inicial se ordena la matriz, no la cambie.

Particione el entero en mordiscos, cada uno corresponderá a los valores 0x0 a 0xf.

Utilice los nibbles como índices para las sub-matrices ordenadas correspondientes. Necesitará 13 conjuntos de 16 sub-matrices (o solo 16 sub-matrices y usar una segunda indirección, o hacer las operaciones de bit en lugar de buscar la respuesta; lo que es más rápido variará según la plataforma).

Concatene las sub-matrices no vacías en la matriz final.

Puedes usar más grande que los nibbles si quieres; los bytes darían 7 conjuntos de 256 matrices y haría más probable que las matrices no vacías requieran concatenación.

Esto supone que las ramas son caras y que los accesos a la matriz en caché son baratos.

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

Echa un vistazo a esto:

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

Debería elegir uno que tenga un costo estable en el peor de los casos ...

Otra opción podría ser mantener la matriz ordenada todo el tiempo, por lo que una adición de una tarjeta mantendría la matriz ordenada automáticamente, de esa manera podría pasar a la clasificación ...

A lo que se refiere JRL es a un tipo de depósito. Como tiene un conjunto discreto finito de valores posibles, puede declarar 52 cubos y simplemente soltar cada elemento en un cubo en el tiempo O (1). Por lo tanto, el tipo de depósito es O (n). Sin la garantía de un número finito de elementos diferentes, la clasificación teórica más rápida es O (n log n), que son cosas como la clasificación por fusión y la clasificación rápida. Es solo un equilibrio de los mejores y peores escenarios entonces.

Pero la respuesta larga es corta, usa el tipo de cubeta.

Si le gusta la sugerencia mencionada anteriormente de mantener una matriz de 52 elementos que siempre mantiene su matriz ordenada, entonces puede mantener otra lista de 7 elementos que haga referencia a los 7 elementos válidos en la matriz de 52 elementos. De esta forma, incluso podemos evitar analizar la matriz de 52 elementos.

Supongo que para que esto sea realmente eficiente, necesitaríamos tener un tipo de estructura de lista vinculada que sea compatible con las operaciones: InsertAtPosition () y DeleteAtPosition () y ser eficiente en eso.

Hay muchos bucles en las respuestas. Dado su requisito de velocidad y el pequeño tamaño del conjunto de datos, no haría CUALQUIER bucles.

No lo he probado, pero sospecho que la mejor respuesta es un tipo de burbuja completamente desenrollado. Probablemente también obtendría una buena cantidad de ventaja si se realiza en ensamblaje.

Sin embargo, me pregunto si este es el enfoque correcto. ¿Cómo vas a analizar una mano de 7 cartas? Creo que terminarás convirtiéndolo en otra representación para el análisis de todos modos. ¿No sería una matriz 4x13 una representación más útil? (Y de todos modos, el problema de clasificación sería discutible).

Teniendo en cuenta que los últimos 5 elementos siempre se ordenan:


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;

ordenar burbujas es tu amigo. Otros tipos tienen demasiados códigos generales y no son adecuados para un pequeño número de elementos

Saludos

Aquí está su clasificación básica de O (n). No estoy seguro de cómo se compara con los demás. Utiliza bucles desenrollados.

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 está buscando una sobrecarga muy baja, clasificación óptima, debe crear una red de clasificación. Puede generar el código para una red de 7 enteros utilizando el algoritmo Bose-Nelson.

Esto garantizaría un número fijo de comparaciones y un número igual de intercambios en el peor de los casos.

El código generado es feo, pero es óptimo.

Sus datos están en una matriz ordenada y supongo que intercambia los dos nuevos si es necesario, así que también ordenados, así a. si desea mantenerlo en su lugar, utilice una forma de clasificación de inserción; segundo. si desea obtener el resultado en otra matriz, haga una fusión copiando.

Con los números pequeños, el corte binario es excesivo, y el corte ternario es apropiado de todos modos: Una nueva tarjeta se dividirá principalmente en dos y tres, a saber. 2 + 3 o 3 + 2, dos cartas en singles y pares, p. 2 + 1 + 2.

Entonces, el enfoque más eficiente en tiempo y espacio para colocar la nueva tarjeta más pequeña es comparar con un [1] (es decir, omitir un [0]) y luego buscar hacia la izquierda o hacia la derecha para encontrar la tarjeta que debe desplazar, luego cambiar y muévete a la derecha (cambiando en lugar de burbujear), comparándolo con la nueva carta más grande hasta que encuentres a dónde va Después de esto, avanzarás de a dos (se han insertado dos cartas). Las variables que contienen las nuevas tarjetas (y los intercambios) deben ser registros.

El enfoque de búsqueda sería más rápido pero usaría más memoria.

Use una red de clasificación, como en este código 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
}

Use la función anterior si desea pasarle un iterador o un puntero y use la función siguiente si desea pasarle los siete argumentos uno por uno. Por cierto, el uso de plantillas permite que los compiladores generen un código realmente optimizado, así que no te olvides del template<> a menos que quieras el código C (o el código de algún otro idioma).

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
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top