Gra w golfa + szybkie sortowanie w C.


11

[ Najnowsza aktualizacja: dostępny program testów porównawczych i wstępne wyniki, patrz poniżej]

Dlatego chcę przetestować kompromis prędkości / złożoności za pomocą klasycznej aplikacji: sortowania.

Napisz funkcję ANSI C, która sortuje tablicę liczb zmiennoprzecinkowych w kolejności rosnącej .

Nie można korzystać z żadnych bibliotek, wywołania systemowe, wielowątkowość lub inline ASM.

Wpisy oceniane na podstawie dwóch składników: długości kodu i wydajności. Punktacja będzie następująca: wpisy zostaną posortowane według długości (log # znaków bez spacji, dzięki czemu można zachować pewne formatowanie) i według wydajności (log # sekund ponad testem porównawczym), a każdy przedział [najlepszy, najgorszy] liniowo znormalizowany do [ 0,1]. Całkowity wynik programu będzie średnią z dwóch znormalizowanych wyników. Najniższy wynik wygrywa. Jeden wpis na użytkownika.

Sortowanie będzie musiało (ewentualnie) być na miejscu (tj. Tablica wejściowa będzie musiała zawierać posortowane wartości w czasie powrotu) i musisz użyć następującej sygnatury, w tym nazw:

void sort(float* v, int n) {

}

Znaki, które należy policzyć: te w sortfunkcji, w tym podpis, plus dodatkowe funkcje przez niego wywoływane (ale bez kodu testowego).

Program musi obsługiwać dowolne wartości liczbowe floati tablice o długości> = 0, do 2 ^ 20.

Włożę wtyczkę sorti jej zależności do programu testującego i skompiluję na GCC (żadnych fantazyjnych opcji). Wprowadzę do niego kilka tablic, zweryfikuję poprawność wyników i całkowity czas działania. Testy będą przeprowadzane na procesorze Intel Core i7 740QM (Clarksfield) pod Ubuntu 13.
Długości tablicy obejmą cały dozwolony zakres, z większą gęstością krótkich tablic. Wartości będą losowe, z rozkładem grubych ogonów (zarówno w zakresie dodatnim, jak i ujemnym). W niektórych testach zostaną uwzględnione powielone elementy.
Program testowy jest dostępny tutaj: https://gist.github.com/anonymous/82386fa028f6534af263
Importuje zgłoszenie jako user.c. Liczba przypadków testowych ( TEST_COUNT) w rzeczywistym teście będzie wynosić 3000. W komentarzach do pytania proszę podać wszelkie uwagi.

Termin: 3 tygodnie (7 kwietnia 2014, 16:00 GMT). Opublikuję test za 2 tygodnie.
Wskazane może być opublikowanie posta blisko terminu, aby uniknąć przekazywania kodu konkurentom.

Wstępne wyniki w momencie publikacji testu porównawczego:
Oto kilka wyników. Ostatnia kolumna pokazuje wynik w procentach, im wyższy, tym lepiej, stawiając Johnny'ego Cage'a na pierwszym miejscu. Algorytmy, które były o rząd wielkości wolniejsze niż reszta, były uruchamiane w podzbiorze testów i ekstrapolowane w czasie. Własność C qsortjest dołączona do porównania (Johnny's jest szybszy!). Przeprowadzę końcowe porównanie w czasie zamknięcia.

wprowadź opis zdjęcia tutaj


3
Czy możesz podać punkt odniesienia? Różne funkcje sortowania działają inaczej w zależności od charakteru danych. Np. Sortowanie bąbelkowe jest szybsze niż szybkie sortowanie stdlib dla małych tablic. Możemy zoptymalizować dla twojego testu porównawczego.
Claudiu

@Claudiu Kiedyś widziałem uroczą krótką wersję Quicksort, która działała równie dobrze jak każda inna na danych, w których każdy element był inny. Ale jeśli niektóre elementy były takie same, działał w absolutnym tempie ślimaka. Nie mówię o znanym problemie złego wyboru osi przestawnej w uporządkowanych / częściowo posortowanych tablicach. Moje dane testowe zostały całkowicie losowo przetasowane. Ta konkretna wersja po prostu nie lubiła duplikatów. Dziwne, ale prawdziwe.
Level River St

3
Witamy w PPCG! Chociaż nie zabraniamy wyzwaniom specyficznym dla języka, zdecydowanie zachęcamy do formułowania pytań w sposób agnostyczny w miarę możliwości. Zastanów się nad kolejnym pytaniem i baw się dobrze z tym!
Jonathan Van Matre

1
@steveverrill: Nie podążam. Nie ma znaczenia, jaka jest twoja jednostka, ponieważ i tak skalujesz ją od 0 do 1. Jeśli min to 1 godzina, a maksimum to 3 godziny, coś, co zajmuje 1,5 godziny, będzie wynosić 0,25 niezależnie od tego, czy min to 60 minut, maksimum to 180 minut i zajmuje 90 minut
Claudiu

1
OP powiedział tylko, że nie ma wbudowanego zestawu - nie mówił nic o wewnętrznych elementach.
Paul R

Odpowiedzi:


6

150 znaków

Szybkie sortowanie.

/* 146 character.
 * sizeup 1.000; speedup 1.000; */
#define REC_SIZE    \
    sort(l, v+n-l); \
    n = l-v;

/* 150 character.
 * sizeup 1.027; speedup 1.038; */
#define REC_FAST  \
    sort(v, l-v); \
    n = v+n-l;    \
    v = l;

void sort(float* v, int n)
{
    while ( n > 1 )
     {
       float* l = v-1, * r = v+n, x = v[n/2], t;
L:
       while ( *++l < x );
       while ( x < (t = *--r) );

       if (l < r)
        {
          *r = *l; *l = t;
          goto L;
        }
       REC_FAST
     }
}

Sprężony.

void sort(float* v, int n) {
while(n>1){float*l=v-1,*r=v+n,x=v[n/2],t;L:while(*++l<x);while(x<(t=*--r));if(l<r){*r=*l;*l=t;goto L;}sort(v,l-v);n=v+n-l;v=l;}
}

Prowadzący wyścig!
Mau

3

150 znaków (bez białych znaków)

void sort(float *v, int n) {
    int l=0;
    float t, *w=v, *z=v+(n-1)/2;

    if (n>0) {
      t=*v; *v=*z; *z=t;
      for(;++w<v+n;)
        if(*w<*v)
        {
          t=v[++l]; v[l]=*w; *w=t;
        }
      t=*v; *v=v[l]; v[l]=t;
      sort(v, l++);
      sort(v+l, n-l);
    }
}

Niesamowite, pierwszy wpis!
Mau

Nie krępuj się opublikować odpowiedź w SSE, a wymienię ją na tablicy wyników, choć interesują mnie „przenośne” rozwiązania tego wyzwania.
Mau

if(*w<*v) { t=v[++l]; v[l]=*w; *w=t; }może byćif(*w<*v) t=v[++l], v[l]=*w, *w=t;
ZAPYTAJ

3

67 70 69 znaków

Wcale nie szybki, ale niezwykle mały. Chyba jest to hybryda między sortowaniem selekcji a algorytmem sortowania bąbelkowego. Jeśli naprawdę próbujesz to przeczytać, powinieneś wiedzieć, że ++i-v-nto samo ++i != v+n.

void sort(float*v,int n){
    while(n--){
        float*i=v-1,t;
        while(++i-v-n)
            *i>v[n]?t=*i,*i=v[n],v[n]=t:0;
    }
}

if(a)b-> a?b:0zapisuje znak.
ugoren

Cóż, ++i-v-njest taka sama, jak ++i != v+ntylko w ramach warunkowego, oczywiście.
wchargin

@ugoren myślę, że opublikowałeś ten komentarz na złą odpowiedź
ZAPYTAJ

@ASKASK, if(*i>v[n])...->*i>v[n]?...:0
ugoren

czy jesteś pewien, że tak działa pierwszeństwo?
ZAPYTAJ

2

123 znaki (+3 nowe linie)

Standardowy rodzaj powłoki, skompresowany.

d,i,j;float t;
void sort(float*v,int n){
for(d=1<<20;i=d/=2;)for(;i<n;v[j]=t)for(t=v[j=i++];j>=d&&v[j-d]>t;j-=d)v[j]=v[j-d];
}  

PS: odkryłem, że wciąż jest 10 razy wolniejszy niż Quicksort. Równie dobrze możesz zignorować ten wpis.


Twój wybór luk może być lepszy. Prawdopodobnie dlatego jest to dużo wolniejsze niż Quicksort. en.wikipedia.org/wiki/Shellsort#Gap_sequences
FDinoff

Byłem zaskoczony, gdy odkryłem, jak bardzo sekwencja odstępów wpływa na prędkość. Dobra sekwencja zbliża się do szybkiego sortowania, ale z mojego doświadczenia pozostaje wolniejsza.
Florian F

Nie bądź dla siebie zbyt surowy. Jesteś na trzecim miejscu.
Kevin

2

395 znaków

Mergesort.

void sort(float* v,int n){static float t[16384];float*l,*r,*p,*q,*a=v,*b=v+n/2,
*c=v+n,x;if(n>1){sort(v,n/2);sort(v+n/2,n-n/2);while(a!=b&&b!=c)if(b-a<=c-b&&b-
a<=16384){for(p=t,q=a;q!=b;)*p++=*q++;for(p=t,q=t+(b-a);p!=q&&b!=c;)*a++=(*p<=
*b)?*p++:*b++;while(p!=q)*a++=*p++;}else{for(l=a,r=b,p=t,q=t+16384;l!=b&&r!=c&&
p!=q;)*p++=(*l<=*r)?*l++:*r++;for(q=b,b=r;l!=q;)*--r=*--q;for(q=t;p!=q;)*a++=
*q++;}}}

Sformatowany.

static float* copy(const float* a, const float* b, float* out)
{   while ( a != b ) *out++ = *a++; return out;
}
static float* copy_backward(const float* a, const float* b, float* out)
{   while ( a != b ) *--out = *--b; return out;
}

static void ip_merge(float* a, float* b, float* c)
{
    /* 64K (the more memory, the better this performs). */
#define BSIZE (1024*64/sizeof(float))
    static float t[BSIZE];

    while ( a != b && b != c )
     {
       int n1 = b - a;
       int n2 = c - b;

       if (n1 <= n2 && n1 <= BSIZE)
        {
          float* p = t, * q = t + n1;
          /* copy [a,b] sequence. */
          copy(a, b, t);
          /* merge. */
          while ( p != q && b != c )
             *a++ = (*p <= *b) ? *p++ : *b++;
          /* copy remaining. */
          a = copy(p, q, a);
        }
       /* backward merge omitted. */
       else
        {
          /* there are slicker ways to do this; all require more support
           * code. */
          float* l = a, * r = b, * p = t, * q = t + BSIZE;
          /* merge until sequence end or buffer end is reached. */
          while ( l != b  && r != c && p != q )
             *p++ = (*l <= *r) ? *l++ : *r++;
          /* compact remaining. */
          copy_backward(l, b, r);
          /* copy buffer. */
          a = copy(t, p, a);
          b = r;
        }
     }
}

void sort(float* v, int n)
{
    if (n > 1)
     {
       int h = n/2;
       sort(v, h); sort(v+h, n-h); ip_merge(v, v+h, v+n);
     }
}

2

331 326 327 312 znaków

Czy Radix sortuje 8 bitów na raz. Używa fantazyjnego bithacka, aby poprawnie uzyskać ujemne liczby zmiennoprzecinkowe (skradzione z http://stereopsis.com/radix.html ). Nie jest tak kompaktowy, ale jest naprawdę szybki (~ 8 razy szybszy niż najszybszy zapis wstępny). Mam nadzieję, że rozmiar kodu szybkiego przekroczenia prędkości ...

#define I for(i=n-1;i>=0;i--)
#define J for(i=0;i<256;i++)
#define R for(r=0;r<4;r++)
#define F(p,q,k) I p[--c[k][q[i]>>8*k&255]]=q[i]

void sort(float *a, int n) {
  int *A = a,i,r,x,c[4][257],B[1<<20];
  R J c[r][i]=0;
  I {
    x=A[i]^=A[i]>>31|1<<31;
    R c[r][x>>8*r&255]++;
  }
  J R c[r][i+1]+=c[r][i];

  F(B,A,0);
  F(A,B,1);
  F(B,A,2);
  F(A,B,3)^(~B[i]>>31|1<<31);
}

2

511 424 znaków

W miejscu radixsort

Aktualizacja: Przełącza na sortowanie wstawiania dla mniejszych rozmiarów macierzy (zwiększa wydajność testu porównawczego czterokrotnie).

#define H p[(x^(x>>31|1<<31))>>s&255]
#define L(m) for(i=0;i<m;i++)
void R(int*a,int n,int s){if(n<64){float*i,*j,x;for(i=a+1;i<a+n;i++){x=*i;for(
j=i;a<j&&x<j[-1];j--)*j=j[-1];*j=x;}}else{int p[513]={},*q=p+257,z=255,i,j,x,t
;L(n)x=a[i],H++;L(256)p[i+1]+=q[i]=p[i];for(z=255;(i=p[z]-1)>=0;){x=a[i];while
((j=--H)!=i)t=x,x=a[j],a[j]=t;a[i]=x;while(q[z-1]==p[z])z--;}if(s)L(256)R(a+p[
i],q[i]-p[i],s-8);}}void sort(float* v,int n){R(v,n,24);}

Sformatowany.

/* XXX, BITS is a power of two. */
#define BITS 8
#define BINS (1U << BITS)
#define TINY 64

#define SWAP(type, a, b) \
    do { type t=(a);(a)=(b);(b)=t; } while (0)

static inline unsigned int floatbit_to_sortable_(const unsigned int x)
{   return x ^ ((0 - (x >> 31)) | 0x80000000);
}

static inline unsigned int sortable_to_floatbit_(const unsigned int x)
{   return x ^ (((x >> 31) - 1) | 0x80000000);
}

static void insertsort_(unsigned int* a, unsigned int* last)
{
    unsigned int* i;
    for ( i = a+1; i < last; i++ )
     {
       unsigned int* j, x = *i;
       for ( j = i; a < j && x < *(j-1); j-- )
          *j = *(j-1);
       *j = x;
     }
}

static void radixsort_lower_(unsigned int* a, const unsigned int size,
  const unsigned int shift)
{
    /* @note setup cost can be prohibitive for smaller arrays, switch to
     * something that performs better in these cases. */
    if (size < TINY)
     {
       insertsort_(a, a+size);
       return;
     }

    unsigned int h0[BINS*2+1] = {}, * h1 = h0+BINS+1;
    unsigned int i, next;

    /* generate histogram. */
    for ( i = 0; i < size; i++ )
       h0[(a[i] >> shift) % BINS]++;

    /* unsigned distribution.
     * @note h0[BINS] == h1[-1] == @p size; sentinal for bin advance. */
    for ( i = 0; i < BINS; i++ )
       h0[i+1] += (h1[i] = h0[i]);

    next = BINS-1;
    while ( (i = h0[next]-1) != (unsigned int) -1 )
     {
       unsigned int x = a[i];
       unsigned int j;
       while ( (j = --h0[(x >> shift) % BINS]) != i )
          SWAP(unsigned int, x, a[j]);
       a[i] = x;
       /* advance bins.
        * @note skip full bins (zero sized bins are full by default). */
       while ( h1[(int) next-1] == h0[next] )
          next--;
     }

    /* @note bins are sorted relative to one another at this point but
     * are not sorted internally. recurse on each bin using successive
     * radii as ordering criteria. */
    if (shift != 0)
       for ( i = 0; i < BINS; i++ )
          radixsort_lower_(a + h0[i], h1[i] - h0[i], shift-BITS);
}

void sort(float* v, int n)
{
    unsigned int* a = (unsigned int*) v;
    int i;

    for ( i = 0; i < n; i++ )
       a[i] = floatbit_to_sortable_(a[i]);

    radixsort_lower_(a, n, sizeof(int)*8-BITS);

    for ( i = 0; i < n; i++ )
       a[i] = sortable_to_floatbit_(a[i]);
}

Ładny! Spróbuj oflagować oryginalną odpowiedź.
Mau

@Mau: Dzięki i zrobię. Chciałem wspomnieć o błędzie w kodzie testowym. W obsadzie do void*w qsort(linia 88) jest zrzucenia arytmetycznej wskaźnika.
MojoJojoBojoHojo

1

121 114 111 znaków

Po prostu szybki i brudny zestaw pęcherzyków z rekurencją. Prawdopodobnie niezbyt wydajny.

void sort(float*v,int n){int i=1;float t;for(;i<n;i++)v[i-1]>(t=v[i])&&(v[i]=v[i-1],v[i-1]=t);n--?sort(v,n):0;}

Lub długa wersja

void sort(float* values, int n) {
  int i=1;  // Start at 1, because we check v[i] vs v[i-1]
  float temp;
  for(; i < n; i++) {
    // If v[i-1] > v[i] is true (!= 0), then swap.
    // Note I am assigning values[i] to temp here. Below I want to use commas
    // so the whole thing fits into one statement, but if you assign temp there you will get sequencing issues (i.e unpredictable swap results)
    values[i - 1] > (temp = values[i]) && (
    // I tried the x=x+y,y=x-y,x=x-y trick, but using a temp
    // turns out to be shorter even if we have to declare the t variable.
      values[i] = values[i - 1], 
      values[i - 1] = temp);
  }

  // If n == 1, we are done. Otherwise, sort the first n - 1 elements recursively. 
  // The 0 is just because the third statement cannot be empty.
  n-- ? sort(values, n) : 0;
}

Nawiasem mówiąc , znalazłem tutaj naprawdę interesujący algorytm: rosettacode.org/wiki/Sorting_algorithms/Pancake_sort#C Ale nie mogę go wystarczająco skompresować, aby pokonać 114 :)
CompuChip

Twój program wydaje się nie wypełniać w niektórych przypadkach i zapisywać poza granicami w innych przypadkach.
Mau

@Mau Testowałem go na niektórych wejściach ręcznie i wydawało się, że działa dobrze, ale z powodu braku czasu nie przetestowałem go zbyt dokładnie, więc jestem pewien, że gdzieś jest jakieś złe zachowanie. Czy mógłbyś opublikować przypadek testowy, w którym napotkałeś problemy?
CompuChip

Program testowy dostępny powyżej :)
Mau

Hmm, próbowałem go uruchomić, dostaję kilka błędów `munmap_chunk (): nieprawidłowy wskaźnik` w części czyszczącej, ale nic z niepowodzenia testu. Jednak masz rację, że występuje błąd „jeden po drugim” i wydaje mi się, że mam pewne problemy z sekwencjonowaniem (lista instrukcji oddzielonych przecinkami nie spełnia moich oczekiwań). Spróbuję to naprawić.
CompuChip

1

221 193 172 znaków

Heapsort - nie najmniejszy, ale na miejscu i gwarantuje zachowanie O (n * log (n)).

static void sink(float* a, int i, int n, float t)
{
    float* b = a+i;

    for ( ; (i = i*2+2) <= n; b = a+i )
     {
       i -= (i == n || a[i] < a[i-1]) ? 1 : 0;

       if (t < a[i])
          *b = a[i];
       else
          break;
     }
    *b = t;
}

void sort(float* a, int n)
{
    int i;
    /* make. */
    for ( i = n/2-1; i >= 0; i-- )
       sink(a, i, n, a[i]);
    /* sort. */
    for ( i = n-1; i > 0; i-- )
     {
       float t = a[i]; a[i] = a[0];
       sink(a, 0, i, t);
     }
}

Sprężony.

void sort(float* a,int n){
#define F(p,q,r,x,y) for(i=n/p;q>0;){t=a[i];r;for(j=x;(b=a+j,j=j*2+2)<=y&&(j-=(j==y||a[j]<a[j-1]),t<a[j]);*b=a[j]);*b=t;}
float*b,t;int i,j;F(2,i--,,i,n)F(1,--i,a[i]=*a,0,i)
}

Możesz zapisać niektóre znaki, odejmując białe znaki. I być może również podpis obowiązkowej funkcji, ale ponieważ są pewne wpisy, które się liczyły, poprosiłem pytającego o wyjaśnienie, czy należy je liczyć.
Jonathan Van Matre

@ user19425: Jeśli uruchomisz program testowy z TEST_COUNT= 3000, wydaje się, że co najmniej jeden test się nie powiedzie.
Mau

1

154 166 znaków

OK, tutaj jest szybszy, ale szybszy.

void sort(float*v,int n){while(n>1){float*j=v,*k=v+n-1,t=*j;while(j<k){while(j<k&&*k>=t)k--;*j=*k;while(j<k&&*j<t)j++;*k=*j;}*k++=t;sort(k,v+n-k);n=j-v;}}

Oto poprawka na przetrwanie posortowanych danych wejściowych. I sformatowane, ponieważ białe znaki się nie liczą.

void sort(float*v, int n){
    while(n>1){
        float*j=v, *k=j+n/2, t=*k;
        *k = *j;
        k = v+n-1;
        while(j<k){
            while(j<k && *k>=t) k--;
            *j=*k;
            while(j<k && *j<t) j++;
            *k=*j;
        }
        *k++ = t;
        sort(k,v+n-k);
        n = j-v;
    }
}

Ta wersja wydaje się w niektórych przypadkach pisać poza granicami, w innych się nie kończy.
Mau

PS: OK, na posortowanym zestawie jest bardzo wolno. Ale opis problemu mówi, że dane wejściowe są losowe.
Florian F

Wartości są losowe. Nigdy nie mówiłem nic o tym, w jakiej kolejności będą :-) Ale tak, są fragmenty obejmujące około 10% wszystkich wartości posortowanych w porządku rosnącym i kolejne 10% w porządku malejącym.
Mau

1
Słusznie. A sort () powinien działać na posortowanych danych wejściowych. Zaktualizuję moje zgłoszenie, a następnie ...
Florian F

1

150 znaków

Shellsort (w / Knuth gap).

void sort(float* v, int n) {
float*p,x;int i,h=0;while(2*(i=h*3+1)<=n)h=i;for(;h>0;h/=3)for(i=h;i<n;i++){x=v[i];for(p=v+i-h;p>=v&&x<*p;p-=h)p[h]=*p;p[h]=x;}
}

Sformatowany.

static void hsort(float* v, const int h, const int n)
{
    int i;
    for (i = h; i < n; i++) {
        float* p, x = v[i];
        for (p = v + i-h; p >= v && x < *p; p -= h)
            p[h] = *p;
        p[h] = x;
    }
}

void sort(float* v, int n)
{
    int i, h = 0;
    while (2*(i = h*3+1) <= n)
        h = i;
    for (; h > 0; h /= 3)
        hsort(v, h, n);
}

1

C 270 (golf)

#define N 1048576
void sort(float*v,int n)
{
float f[N],g;
int m[N],i,j,k,x;
g=v[0];k=0;
for(i=0;i<n;i++){for(j=0;j<n;j++){if(m[j]==1)continue;if(v[j]<g){g=v[j];k=j;}}f[i]=g;m[k]=1;for(x=0;x<n;x++){if(m[x]==0){g=v[x];k=x;break;}}}
for(i=0;i<n;i++){v[i]=f[i];}
}

Objaśnienie: Pusta tablica służy do przechowywania każdej kolejnej minimalnej liczby. Tablica int to maska ​​z wartością 0, która wskazuje, że liczba nie została jeszcze skopiowana. Po uzyskaniu wartości minimalnej maska ​​= 1 pomija już używane liczby. Następnie tablica jest kopiowana z powrotem do oryginału.

Zmieniłem kod, aby wyeliminować użycie funkcji bibliotecznych.


0

144

Bezwstydnie wziąłem kod Johnny'ego, dodałem drobną optymalizację i skompresowałem kod w bardzo brudny sposób. Powinien być krótszy i szybszy.

Zauważ, że w zależności od twojego kompilatora sort (q, v + n- ++ q) należy zastąpić sort (++ q, v + nq).

#define w ;while(
void sort(float*v, int n){
    w n>1){
        float *p=v-1, *q=v+n, x=v[n/2], t
        w p<q){
            w *++p<x )
            w *--q>x );
            if( p<q ) t=*p, *p=*q, *q=t;
        }
        sort(q,v+n- ++q);
        n = p-v;
    }
}

Właściwie zacząłem tworzyć kod i go optymalizować, ale wygląda na to, że Johnny już dokonał właściwych wyborów. Więc skończyłem z quasi jego kodem. Nie myślałem o sztuczce goto, ale mogłem się obejść.


0

228 znaków

Radixsort.

void sort(float* v, int n) {
#define A(x,y,z) for(x=y;x<z;x++)
#define B h[(a[i]^(a[i]>>31|1<<31))>>j*8&255]
    int m[1<<20],*a=v,*b=m,*t,i,j;
    A(j,0,4) {
        int h[256] = {};
        A(i,0,n) B++;
        A(i,1,256) h[i] += h[i-1];
        for (i = n-1; i >= 0; i--)
            b[--B] = a[i];
        t = a, a = b, b = t;
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.