Pergunta

Esta é uma parte de um programa que analisa as probabilidades do poker, especificamente Texas Hold'em. Eu tenho um programa que eu estou feliz com, mas precisa de algumas pequenas otimizações para ser perfeito.

Eu uso deste tipo (entre outros, claro):

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

Há duas coisas sobre essa matriz que pode ser importante ao decidir como classificá-lo:

  1. Cada item é um valor de 0 a 51. Nenhum outro valor é possível.
  2. Não há duplicatas. Nunca.

Com esta informação, o que é o absolutamente mais rápido maneira de classificar essa matriz? Eu uso Delphi, código de modo pascal seria o melhor, mas eu posso ler C e pseudo, embora um pouco mais lentamente: -)

No momento eu uso quicksort, mas o engraçado é que este é quase nenhum mais rápido do que bubblesort! Possível por causa do pequeno número de itens. As contagens de classificação para quase 50% do tempo total de execução do método.

EDIT:

Mason Wheeler perguntou por que é necessário otimizar. Uma razão é que o método será chamado 2118760 vezes.

Informações básicas do poker: Todos os jogadores recebem duas cartas (o bolso) e, em seguida, cinco cartas são dadas na tabela (os 3 primeiros são chamados o flop, o próximo é a vez ea última é o rio Cada jogador escolhe. as cinco melhores cartas para fazer a sua mão)

Se eu tiver dois cartões no bolso, P1 e P2, vou usar os seguintes loops para gerar todas as combinações possíveis:

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;

Enquanto escrevo esta nota eu mais uma coisa: Os últimos cinco elementos do array serão sempre classificadas, por isso é apenas uma questão de colocar os dois primeiros elementos na posição certa na matriz. Isso deve simplificar as coisas um pouco.

Assim, a nova pergunta é: Qual é a maneira mais rápida possível classificar um array de 7 inteiros quando os últimos 5 elementos já estão classificadas. Eu acredito que este poderia ser resolvido com um par de se da e swaps (?): -)

Foi útil?

Solução

Eu não sei muito sobre Texas Hold'em: que importa o que P1 terno e P2 são, ou será que ele só importa se eles são do mesmo naipe ou não? Se apenas terno (P1) == terno (P2) questões, então você pode separar os dois casos, você tem apenas 13x12 / 2 possibilidades diferentes para P1 / P2, e você pode facilmente precalculate uma mesa para os dois casos.

Caso contrário, gostaria de sugerir algo como isto:

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

(esta é apenas uma demonstração para P1 um cartão, você teria que expandir isso para P2, mas eu acho que isso é simples. Embora ele vai ser um monte de digitação ...) Dessa forma, a classificação não tomar qualquer momento a todos. As permutações gerados já estão ordenados.

Outras dicas

Para um conjunto muito pequeno, ordenação por inserção geralmente pode bater quicksort porque tem sobrecarga muito baixa.

WRT sua edição, se você já está na maior parte em ordem de classificação (nos últimos 5 elementos já estão classificadas), ordenação por inserção é definitivamente o caminho a percorrer. Em um conjunto quase-ordenada de dados, ele vai bater quicksort cada vez, mesmo para grandes conjuntos. (Especialmente para grandes conjuntos! Isto é melhor cenário de inserção do tipo e pior caso de quicksort.)

Não sei como você está implementando isso, mas o que você pode fazer é ter uma matriz de 52 em vez de 7, e apenas inserir o cartão no slot diretamente quando você obtê-lo já que nunca podem ser duplicados, de que maneira você nunca tem que classificar a matriz. Isso pode ser mais rápido, dependendo de como a sua utilização.

Existem apenas 5040 permutações de 7 elementos. Você pode programmaticaly gerar um programa que se encontra aquele representado pela sua entrada em um número mínimo de comparações. Vai ser uma grande árvore de instruções if-then-else, cada comparando um par fixo de nós, por exemplo if (a[3]<=a[6]).

A parte difícil é decidir qual 2 elementos para comparar em um nó interno particular. Para isso, você tem que levar em conta os resultados das comparações nos gânglios ancestral da raiz ao nó particular (por exemplo a[0]<=a[1], not a[2]<=a[7], a[2]<=a[5]) eo conjunto de permutações possíveis que satisfaçam as comparações. Comparar o par de elementos que se divide o conjunto em que partes iguais quanto possível (minimizar o tamanho da maior parte).

Uma vez que você tem a permutação, é trivial para classificá-lo em um conjunto mínimo de swaps.

Uma vez que os últimos 5 itens já estão classificadas, o código pode ser escrito apenas para reposicionar os 2 primeiros itens. Desde que você está usando Pascal, eu tenho escrito e testado um algoritmo de ordenação que pode executar 2,118,760 vezes em cerca de 62 milissegundos.

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. Procurar elemento mínimo e máximo de uma vez e colocá-los em conjunto resultante. Repita três vezes. (EDIT: Não, eu não vou tentar medir a velocidade 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

Este é o método mais rápido: uma vez que a lista de 5 cartas já estão classificados, classificar a lista de duas cartas (a comparar & swap), e em seguida, mesclar as duas listas, que é O (k * (5 + 2) . neste caso (k) será normalmente de 5: o teste de circuito (1), a comparação (2), a cópia (3), o incremento-lista de entrada (4) e a lista de saída incremento (5), que é 35. + 2.5. O lance em inicialização de loop e você terá 41,5 declarações, total.

Você também pode desenrolar dos laços que iria salvá-lo talvez 8 declarações ou execução, mas fazer toda a rotina de cerca de 4-5 vezes mais do que mexer maio com o seu rácio de cache hit instrução.

Dado P (0 a 2), C (0 a 5) e copiar a H (0-6) com C () já classificadas (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

E note que este é mais rápido do que o outro algoritmo que seria "mais rápido" se você tivesse que verdadeiramente classificar todos os 7 cartões: usar uma máscara de bits (52) para mapear e bit-set todos os 7 cartas em que gama de todos os possíveis 52 cartas (o bit de máscara), e, então, verificar o bit de máscara, a fim procurando os 7 bits que são definidas. Que leva 60-120 declarações na melhor das hipóteses (mas é ainda mais rápido do que qualquer outra abordagem de classificação).

Por sete números, o algoritmo mais eficiente que existe com relação ao número de comparações é Ford-Johnson. Na verdade, wikipedia faz referência a um papel, facilmente encontrado no Google, essa é a melhor reivindicações Ford-Johnson para até 47 números. Infelizmente, as referências a da Ford-Johnson não são tão fáceis de encontrado, e o algoritmo usa algumas estruturas de dados complexos.

Ele aparece em The Art of Computer Programming, Volume 3, por Donald Knuth, se você tem acesso a esse livro.

Há um papel que descreve FJ e uma versão mais eficiente da memória aqui .

De qualquer forma, por causa da sobrecarga de memória desse algoritmo, duvido que iria valer a pena para inteiros, como o custo da comparação de dois números inteiros é bastante barato em comparação com o custo de alocação de memória e manipulação de ponteiros.

Agora, você mencionou que 5 cartas já estão classificadas, e você só precisa inserir dois. Você pode fazer isso com a inserção tipo mais eficiente como este:

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

Como você faz isso vai depender da estrutura de dados. Com uma variedade você estará trocando cada elemento, de modo local P1 no 1º, P2 e 7 (alto a baixo ordenou), e depois troca P1, e então P2 para baixo. Com uma lista, você só precisa corrigir os ponteiros conforme o caso.

No entanto, mais uma vez, por causa da particularidade do seu código, é realmente melhor se você seguir Nikie sugestão e apenas gerar o para loops apropriately para cada variação em que P1 e P2 pode aparecer na lista.

Por exemplo, tipo P1 e P2 para que P1

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

Em seguida, chamar uma função que passa Po1, PO2, P1, P2, C1, C2, C3, C4, C5, e ter esta função retornar todas as permutações possíveis com base no Po1 e PO2 (que é 36 combinações).

Pessoalmente, eu acho que é o mais rápido você pode começar. Você completamente evitar ter de pedir qualquer coisa, porque os dados serão pré-ordenada. Você incorrer em algumas comparações de qualquer maneira para calcular os começos e fins, mas o seu custo é minimizado como a maioria deles será sobre os laços ultraperiféricas, para que eles não serão repetidos muito. E eles podem até mesmo ser mais otimizada ao custo de mais duplicação de código.

Para 7 elementos, há apenas algumas opções. Você pode facilmente escrever um gerador que produz método para classificar todas as combinações possíveis de 7 elementos. Algo como este método por 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]
    ...
}

Do método claro para 7 elementos será maior, mas não é tão difícil de gerar.

O código abaixo é próxima do ideal. Pode ser feito melhor, compondo uma lista a ser percorrida ao fazer a árvore, mas estou sem tempo no momento. Felicidades!

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

No código pseudo:

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;

É uma aplicação de balde tipo , que geralmente deve ser mais rápido do que qualquer da comparação ordenações que foram sugeridas.

Nota: A segunda parte pode também ser implementado por iteração sobre bits em tempo linear, mas na prática isso pode não ser mais rápida:

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;

Assumindo que você precisa de uma variedade de cartões no final do mesmo.

Mapa dos cartões originais para os bits em um número inteiro de 64 bits (ou qualquer inteiro com> = 52 bits).

Se durante o mapeamento inicial da matriz é classificada, não mudá-lo.

Reparte-se o número inteiro em mordidelas -. Cada corresponderão a valores 0x0 para 0xf

Use o petiscos como índices de sub-matrizes ordenadas correspondente. Você vai precisar de 13 conjuntos de 16 sub-matrizes (ou apenas 16 sub-matrizes e utilizar um segundo engano, ou fazer as ops bits em vez de olhar a resposta-se, o que é mais rápido irá variar por plataforma).

concatenar os vazios não-sub-matrizes para a matriz final.

Você pode usar maior do que petiscos, se quiser; bytes daria 7 conjuntos de 256 matrizes e torná-lo mais provável que as matrizes não vazios exigem concatenação.

Isso pressupõe que as sucursais são caros e matriz em cache acessa barato.

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

Dê uma olhada nisso:

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

Você precisa escolher um que terá um estábulo pior custo caso ...

Outra opção poderia ser a de manter a matriz classificados o tempo todo, por isso, uma adição de um cartão iria manter a matriz classificada automaticamente, de que maneira você pode pular para a classificação ...

O que JRL está se referindo é uma espécie de balde. Desde que você tem um conjunto discreto finito de valores possíveis, você pode declarar 52 baldes e apenas uma gota cada elemento em um balde em O (1) tempo. Daí balde tipo é O (n). Sem a garantia de um número finito de elementos diferentes, o tipo mais rápido teórico é O (n log n) que coisas como merge sort uma rápida tipo são. É apenas um equilíbrio de melhores e piores cenários depois.

Mas a resposta longa curto, tipo uso balde.

Se você como o acima mencionado sugestão para manter uma matriz 52 elemento que mantém sempre a sua matriz classificada, então pode ser que você poderia manter outra lista de 7 elementos que fazem referência os 7 elementos válidos na matriz 52 elemento. Desta forma, podemos até mesmo evitar analisar a matriz 52 elemento.

Eu acho que para que isso seja realmente eficiente, seria necessário ter um tipo ligada lista de estrutura que ser operações suporta:. InsertAtPosition () e DeleteAtPosition () e ser eficiente nesse

Há um monte de loops nas respostas. Dada a sua exigência de velocidade e do tamanho minúsculo do conjunto de dados que eu não faria ANY loops.

Eu não tentei, mas eu suspeito que a melhor resposta é uma bolha tipo totalmente desenrolada. Seria provavelmente também ganhar uma boa quantidade de vantagem de ser feito em conjunto.

Gostaria de saber se este é o caminho certo, no entanto. Como você está indo para analisar uma mão 7 cartão ?? Eu acho que você vai acabar convertendo-o em alguma outra representação para análise de qualquer maneira. Não seria uma matriz 4X13 ser uma representação mais útil? (E isso tornaria o moot problema de classificação, de qualquer maneira.)

Considerando que os últimos 5 elementos são sempre classificadas:


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 é seu amigo. Outros tipos têm muitos códigos gerais e não é adequado para pequeno número de elementos

Felicidades

Aqui é o seu básicos O (n) tipo. Não tenho certeza como ele se compara com os outros. Ele usa laços desenroladas.

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 você estiver procurando por uma sobrecarga muito baixa, ideal tipo, você deve criar uma rede de classificação. Você pode gerar o código para uma rede 7 inteiro usando o algoritmo de Bose-Nelson.

Isso garantimos um número fixo de compara e um número igual de swaps no pior caso.

O código gerado é feio, mas é ideal.

Seus dados está em um array ordenado e eu vou assumir que você trocar o novo dois, se necessário, para também classificadas, de modo uma. se você quiser mantê-lo no lugar, em seguida, usar uma forma de ordenação por inserção; b. se você quiser tê-lo o resultado em outro array fazer uma fusão copiando.

Com os números pequenos, costeleta binário é um exagero, e pique ternária é de qualquer maneira apropriada: Um novo cartão será principalmente como dividido em dois e três, viz. 2 + 3 + 2 ou 3, duas placas em individuais e pares, por exemplo 2 + 1 + 2.

Assim, a abordagem eficiente do espaço-tempo mais para colocar o novo cartão de menor é para comparar com a [1] (viz. Pule a [0]) e em seguida, procure a esquerda ou direita para encontrar o cartão que deve substituir, em seguida, troca e movimento certo (mudança, em vez de borbulhando), comparando com o cartão novo e maior até encontrar onde ele vai. Após isso, você vai estar mudando para a frente em pares (foram inseridos dois cartões). As variáveis ??segurando os novos cartões (e swaps) deve ser registros.

O olhar de abordagem seria mais rápido, mas usar mais memória.

Use uma rede de classificação, como o código neste 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 a função acima, se você quiser passar um iterador ou um ponteiro e usar a função abaixo se você quiser passar os sete argumentos, um por um. BTW, o uso de modelos permite compiladores para gerar o código realmente otimizado para não começar o passeio do template<> menos que você queira código C (ou código de algum outro 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top