Каков самый быстрый способ отсортировать массив из 7 целых чисел?

StackOverflow https://stackoverflow.com/questions/1415173

Вопрос

Это часть программы, которая анализирует шансы в покере, в частности в Техасском Холдеме.У меня есть программа, которой я доволен, но для того, чтобы она стала идеальной, требуется небольшая оптимизация.

Я использую этот тип (среди прочих, конечно):

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

В этом массиве есть две вещи, которые могут оказаться важными при принятии решения о его сортировке:

  1. Каждый элемент имеет значение от 0 до 51.Никакие другие значения невозможны.
  2. Дубликатов нет.Никогда.

Что, обладая этой информацией, абсолютно самый быстрый способ отсортировать этот массив?Я использую Delphi, поэтому лучше всего подойдет код на Паскале, но я могу читать C и псевдо, хотя и немного медленнее :-)

На данный момент я использую быструю сортировку, но самое смешное, что это почти не быстрее, чем пузырьковая сортировка!Возможно из-за небольшого количества предметов.Сортировка занимает почти 50% общего времени работы метода.

РЕДАКТИРОВАТЬ:

Мейсон Уиллер спросил, почему необходимо оптимизировать.Одна из причин заключается в том, что метод будет вызываться 2118760 раз.

Основная информация о покере:Всем игрокам раздаются по две карты (карман), а затем на стол сдаются пять карт (первые три карты называются флопом, следующая — терном, а последняя — ривером).Каждый игрок выбирает пять лучших карт, чтобы составить свою руку)

Если у меня в кармане две карты, P1 и P2, я буду использовать следующие циклы для генерации всех возможных комбинаций:

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;

Когда я пишу это, я замечаю еще одну вещь:Последние пять элементов массива всегда будут отсортированы, поэтому остается лишь разместить первые два элемента в правильном положении в массиве.Это должно немного упростить ситуацию.

Итак, новый вопрос:Каков самый быстрый способ отсортировать массив из 7 целых чисел, если последние 5 элементов уже отсортированы.Я считаю, что это можно решить с помощью пары (?) if и свопов :-)

Это было полезно?

Решение

Я не так уж много знаю о Техасском Холдеме:Имеет ли значение, какой масти P1 и P2, или имеет значение только то, принадлежат ли они одной масти или нет?Если имеет значение только костюм(P1)==костю(P2), то вы можете разделить эти два случая, у вас есть только 13x12/2 различных возможностей для P1/P2, и вы можете легко предварительно рассчитать таблицу для двух случаев.

В противном случае я бы предложил что-то вроде этого:

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

(это всего лишь демонстрация для одной карты P1, вам придется расширить ее для P2, но я думаю, что это просто.Хотя это будет много печатать ...) таким образом, сортировка вообще не займет время.Сгенерированные перестановки уже упорядочены.

Другие советы

Для очень маленького набора сортировка вставкой обычно может превзойти быструю сортировку, поскольку у нее очень низкие накладные расходы.

WRT ваше редактирование: если вы уже в основном находитесь в порядке сортировки (последние 5 элементов уже отсортированы), сортировка вставкой определенно подойдет.В почти отсортированном наборе данных он каждый раз превосходит быструю сортировку, даже для больших наборов.(Особенно для больших комплектов!Это лучший сценарий сортировки вставками и худший вариант быстрой сортировки.)

Не знаю, как вы это реализуете, но вы могли бы иметь массив из 52 вместо 7 и просто вставлять карту в слот сразу, как только получите ее, поскольку дубликатов быть не может, поэтому у вас никогда не будет дубликатов. для сортировки массива.Это может быть быстрее в зависимости от того, как оно используется.

Существует всего 5040 перестановок семи элементов.Вы можете программно создать программу, которая найдет тот, который представлен вашими входными данными, за минимальное количество сравнений.Это будет большое дерево if-then-else инструкции, каждая из которых сравнивает, например, фиксированную пару узлов if (a[3]<=a[6]).

Сложнее всего решить, какие два элемента сравнивать в конкретном внутреннем узле.Для этого необходимо учитывать результаты сравнений в узлах-предках от корня до конкретного узла (например a[0]<=a[1], not a[2]<=a[7], a[2]<=a[5]) и набор возможных перестановок, удовлетворяющих сравнению.Сравните пару элементов, которая разбивает набор на как можно более равные части (минимизируйте размер большей части).

Если у вас есть перестановка, ее легко отсортировать с помощью минимального набора перестановок.

Поскольку последние 5 элементов уже отсортированы, можно написать код только для изменения положения первых 2 элементов.Поскольку вы используете Паскаль, я написал и протестировал алгоритм сортировки, который может выполняться 2 118 760 раз примерно за 62 миллисекунды.

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;

Используйте мини-сортировку.Найдите одновременно минимальный и максимальный элемент и поместите их в результирующий массив.Повторите три раза.(РЕДАКТИРОВАТЬ:Нет, я не буду пытаться измерить скорость теоретически :_))

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

Это самый быстрый метод:поскольку список из 5 карточек уже отсортирован, отсортируйте список из двух карточек (сравнение и замена), а затем объедините два списка, что равно O(k * (5+2).В этом случае (k) обычно будет равно 5:проверка цикла (1), сравнение (2), копирование (3), приращение входного списка (4) и приращение выходного списка (5).Это 35+2,5.Добавьте инициализацию цикла, и вы получите всего 41,5 операторов.

Вы также можете развернуть циклы, что сэкономит вам, возможно, 8 операторов или выполнения, но сделает всю процедуру примерно в 4-5 раз длиннее, что может испортить коэффициент попадания в кэш инструкций.

Приведен P (от 0 до 2), C (от 0 до 5) и копирование в H (от 0 до 6) с уже сортированным (восходящим):

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

И обратите внимание, что это быстрее, чем другой алгоритм, который был бы «самым быстрым», если бы вам пришлось по-настоящему отсортировать все 7 карточек:используйте битовую маску (52), чтобы отобразить и установить все 7 карт в этот диапазон из всех возможных 52 карт (битовая маска), а затем просканировать битовую маску в поисках 7 установленных битов.В лучшем случае для этого потребуется 60–120 операторов (но это все равно быстрее, чем любой другой подход к сортировке).

Для семи чисел наиболее эффективным существующим алгоритмом с точки зрения количества сравнений является алгоритм Форда-Джонсона.Фактически, Википедия ссылается на статью, которую легко найти в Google, в которой утверждается, что Ford-Johnson является лучшим по 47 числам.К сожалению, ссылки на Форда-Джонсона найти не так-то просто, а алгоритм использует некоторые сложные структуры данных.

Он появляется в третьем томе «Искусства компьютерного программирования» Дональда Кнута, если у вас есть доступ к этой книге.

Есть статья, описывающая FJ и более эффективную версию памяти. здесь.

В любом случае, из-за накладных расходов памяти, связанных с этим алгоритмом, я сомневаюсь, что для целых чисел оно того стоит, поскольку стоимость сравнения двух целых чисел довольно дешева по сравнению со стоимостью выделения памяти и манипулирования указателями.

Вы упомянули, что 5 карточек уже рассортированы, и вам просто нужно вставить две.Наиболее эффективно это можно сделать с помощью сортировки вставками следующим образом:

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

Как вы это сделаете, будет зависеть от структуры данных.В массиве вы будете менять местами каждый элемент, поэтому поместите P1 на 1-й, P2 и 7-й (в порядке от высокого к меньшему), а затем поменяйте местами P1 вверх, а затем P2 вниз.В случае списка вам просто нужно исправить указатели соответствующим образом.

Однако еще раз, из-за особенностей вашего кода, будет лучше, если вы будете следовать Ники предложение и просто сгенерируйте циклы for для каждого варианта, в котором P1 и P2 могут появиться в списке.

Например, отсортируйте P1 и P2 так, чтобы P1 < P2.Давайте сделаем Po1 и Po2 позициями от 0 до 6 из P1 и P2 в списке.Затем сделайте следующее:

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

Затем вы вызываете функцию, передающую Po1, Po2, P1, P2, C1, C2, C3, C4, C5, и эта функция возвращает все возможные перестановки на основе Po1 и Po2 (это 36 комбинаций).

Лично я думаю, что это самое быстрое, что вы можете получить.Вам полностью не придется ничего заказывать, поскольку данные будут предварительно заказаны.В любом случае вам придется выполнить некоторые сравнения, чтобы вычислить начало и конец, но их стоимость сведена к минимуму, поскольку большинство из них будут находиться на самых внешних циклах, поэтому они не будут часто повторяться.И их можно даже более оптимизировать за счет большего дублирования кода.

Для 7 стихий вариантов всего несколько.Вы можете легко написать генератор, который создает метод для сортировки всех возможных комбинаций из 7 элементов.Что-то вроде этого метода для 3 элементов:

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

Конечно, метод для 7 элементов будет больше, но сгенерировать его не так уж и сложно.

Код ниже близок к оптимальному.Это можно было бы сделать лучше, составив список, который нужно будет пройти при создании дерева, но сейчас у меня нет времени.Ваше здоровье!

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

В псевдокоде:

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;

Это приложение сортировка ведром, что обычно должно быть быстрее, чем любой из предложенных видов сравнения.

Примечание: Вторую часть также можно реализовать путем перебора битов за линейное время, но на практике это может быть не быстрее:

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;

Предполагая, что вам нужен массив карточек в конце.

Сопоставьте исходные карты с битами 64-битного целого числа (или любого целого числа с >= 52 бита).

Если при первоначальном сопоставлении массив отсортирован, не меняйте его.

Разделите целое число на полубайты — каждый будет соответствовать значениям от 0x0 до 0xf.

Используйте полубайты в качестве индексов для соответствующих отсортированных подмассивов.Вам понадобится 13 наборов по 16 подмассивов (или просто 16 подмассивов и используйте вторую косвенность или выполняйте битовые операции вместо поиска ответа;что быстрее, зависит от платформы).

Объедините непустые подмассивы в окончательный массив.

Если хотите, вы можете использовать больше, чем кусочки;байты дадут 7 наборов по 256 массивов и повысят вероятность того, что непустые массивы потребуют объединения.

Это предполагает, что ветки обходятся дорого, а доступ к кэшированному массиву обходится дешево.

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

Взгляни на это:

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

Вам нужно будет выбрать тот, который будет иметь стабильную стоимость в худшем случае...

Другим вариантом может быть постоянная сортировка массива, поэтому добавление карты будет автоматически сортировать массив, и вы сможете перейти к сортировке...

JRL имеет в виду сортировку ведер.Поскольку у вас есть конечный дискретный набор возможных значений, вы можете объявить 52 сегмента и просто помещать каждый элемент в блок за время O(1).Следовательно, сортировка корзинами равна O(n).Без гарантии конечного числа различных элементов самая быстрая теоретическая сортировка — это O(n log n), каковыми являются такие вещи, как сортировка слиянием и быстрая сортировка.Тогда это просто баланс лучшего и худшего сценариев.

Но если коротко, используйте сортировку по кольцу.

Если вам нравится вышеупомянутое предложение сохранить массив из 52 элементов, который всегда сохраняет ваш массив отсортированным, возможно, вы могли бы сохранить другой список из 7 элементов, который будет ссылаться на 7 допустимых элементов в массиве из 52 элементов.Таким образом, мы можем даже избежать анализа массива из 52 элементов.

Я думаю, чтобы это было действительно эффективно, нам понадобится структура типа связанного списка, которая бы поддерживала операции:InsertAtPosition() и DeleteAtPosition() и будьте эффективны в этом.

В ответах много зацикленностей.Учитывая его требования к скорости и крошечный размер набора данных, я бы не стал этого делать. ЛЮБОЙ петли.

Я не пробовал, но подозреваю, что лучший ответ — это полностью развернутая сортировка пузырьком.Это также, вероятно, получит немало преимуществ от выполнения на ассемблере.

Хотя мне интересно, правильный ли это подход.Как вы собираетесь анализировать 7-карточную руку?Я думаю, что в конечном итоге вам все равно придется преобразовать его в какое-то другое представление для анализа.Не будет ли массив 4х13 более полезным представлением?(И в любом случае это сделало бы вопрос сортировки спорным.)

Учитывая, что последние 5 элементов всегда сортируются:


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;

Сортировка пузырьком — ваш друг.Другие виды имеют слишком много служебных кодов и не подходят для небольшого количества элементов.

Ваше здоровье

Вот ваша базовая сортировка O(n).Я не уверен, как он по сравнению с другими.Он использует развернутые циклы.

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;

Если вы ищете оптимальную сортировку с минимальными накладными расходами, вам следует создать сеть сортировки.Вы можете сгенерировать код для сети из 7 целых чисел, используя алгоритм Бозе-Нельсона.

Это гарантировало бы фиксированное количество сравнений и равное количество свопов в худшем случае.

Сгенерированный код некрасив, но оптимален.

Ваши данные находятся в отсортированном массиве, и я предполагаю, что вы обменяете новыми двумя при необходимости, так что также отсортировано, так что.если вы хотите сохранить его на месте, используйте форму сортировки вставками;б.если вы хотите, чтобы результат был в другом массиве, выполните слияние путем копирования.

При небольших числах бинарное прерывание является излишним, а троичное в любом случае уместно:Одну новую карту лучше всего разделить на две и три, а именно.2+3 или 3+2, две карты в одиночные и пары, например,2+1+2.

Таким образом, наиболее эффективный подход к размещению новой карты меньшего размера — это сравнение с [1] (т.пропустите a[0]), а затем выполните поиск влево или вправо, чтобы найти карту, которую она должна сместить, затем поменяйте местами и переместите вправо (смещаясь, а не всплывая), сравнивая с новой картой большего размера, пока не найдете, куда она идет.После этого вы переместитесь вперед на двойки (вставлены две карты).Переменные, содержащие новые карты (и свопы), должны быть регистрами.

Подход поиска будет быстрее, но будет использовать больше памяти.

Используйте сеть сортировки, как в этом коде 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
}

Используйте функцию выше, если вы хотите передать ей итератор или указатель, и используйте функцию ниже, если вы хотите передать ей семь аргументов один за другим.Кстати, использование шаблонов позволяет компиляторам генерировать действительно оптимизированный код, так что не увлекайтесь template<> если вам не нужен код C (или код какого-либо другого языка).

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
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top