[ 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 sort
funkcji, w tym podpis, plus dodatkowe funkcje przez niego wywoływane (ale bez kodu testowego).
Program musi obsługiwać dowolne wartości liczbowe float
i tablice o długości> = 0, do 2 ^ 20.
Włożę wtyczkę sort
i 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 qsort
jest dołączona do porównania (Johnny's jest szybszy!). Przeprowadzę końcowe porównanie w czasie zamknięcia.
źródło
Odpowiedzi:
150 znaków
Szybkie sortowanie.
Sprężony.
źródło
150 znaków (bez białych znaków)
źródło
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;
67 7069 znakówWcale 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-n
to samo++i != v+n
.źródło
if(a)b
->a?b:0
zapisuje znak.++i-v-n
jest taka sama, jak++i != v+n
tylko w ramach warunkowego, oczywiście.if(*i>v[n])...
->*i>v[n]?...:0
123 znaki (+3 nowe linie)
Standardowy rodzaj powłoki, skompresowany.
PS: odkryłem, że wciąż jest 10 razy wolniejszy niż Quicksort. Równie dobrze możesz zignorować ten wpis.
źródło
395 znaków
Mergesort.
Sformatowany.
źródło
331326327312 znakówCzy 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 ...
źródło
511424 znakówW miejscu radixsort
Aktualizacja: Przełącza na sortowanie wstawiania dla mniejszych rozmiarów macierzy (zwiększa wydajność testu porównawczego czterokrotnie).
Sformatowany.
źródło
void*
wqsort
(linia 88) jest zrzucenia arytmetycznej wskaźnika.121114111 znakówPo prostu szybki i brudny zestaw pęcherzyków z rekurencją. Prawdopodobnie niezbyt wydajny.
Lub długa wersja
źródło
221193172 znakówHeapsort - nie najmniejszy, ale na miejscu i gwarantuje zachowanie O (n * log (n)).
Sprężony.
źródło
TEST_COUNT
= 3000, wydaje się, że co najmniej jeden test się nie powiedzie.154166 znakówOK, tutaj jest szybszy, ale szybszy.
Oto poprawka na przetrwanie posortowanych danych wejściowych. I sformatowane, ponieważ białe znaki się nie liczą.
źródło
150 znaków
Shellsort (w / Knuth gap).
Sformatowany.
źródło
C 270 (golf)
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.
źródło
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).
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ść.
źródło
228 znaków
Radixsort.
źródło