[ Dernière mise à jour: programme de référence et résultats préliminaires disponibles, voir ci-dessous]
Je veux donc tester le compromis vitesse / complexité avec une application classique: le tri.
Écrivez une fonction ANSI C qui trie un tableau de nombres à virgule flottante dans l' ordre croissant .
Vous ne pouvez utiliser aucune bibliothèque, appel système, multithreading ou ASM en ligne.
Entrées jugées sur deux composantes: la longueur du code et les performances. Notation comme suit: les entrées seront triées par longueur (journal de # caractères sans espace blanc, afin que vous puissiez conserver une mise en forme) et par performance (journal de # secondes sur une référence), et chaque intervalle [meilleur, pire] normalisé linéairement à [ 0,1]. Le score total d'un programme sera la moyenne des deux scores normalisés. Le score le plus bas l'emporte. Une entrée par utilisateur.
Le tri devra (éventuellement) être en place (c'est-à-dire que le tableau d'entrée devra contenir des valeurs triées au moment du retour), et vous devez utiliser la signature suivante, y compris les noms:
void sort(float* v, int n) {
}
Caractères à compter: ceux de la sort
fonction, signature incluse, plus les fonctions supplémentaires appelées par celle-ci (mais sans inclure le code de test).
Le programme doit gérer toute valeur numérique float
et tableaux de longueur> = 0, jusqu'à 2 ^ 20.
Je vais brancher sort
et ses dépendances dans un programme de test et compiler sur GCC (pas d'options fantaisistes). Je vais y alimenter un tas de tableaux, vérifier l'exactitude des résultats et le temps d'exécution total. Les tests seront exécutés sur un Intel Core i7 740QM (Clarksfield) sous Ubuntu 13.
Les longueurs de baies couvriront toute la plage autorisée, avec une densité plus élevée de baies courtes. Les valeurs seront aléatoires, avec une distribution de queue grasse (à la fois dans les plages positives et négatives). Des éléments dupliqués seront inclus dans certains tests.
Le programme de test est disponible ici: https://gist.github.com/anonymous/82386fa028f6534af263
Il importe la soumission en tant que user.c
. Le nombre de cas de test ( TEST_COUNT
) dans le benchmark réel sera de 3000. Veuillez fournir vos commentaires dans les commentaires de la question.
Délai: 3 semaines (7 avril 2014, 16h00 GMT). Je posterai le benchmark dans 2 semaines.
Il peut être conseillé de publier près de la date limite pour éviter de donner votre code aux concurrents.
Résultats préliminaires, à la date de publication du benchmark:
Voici quelques résultats. La dernière colonne montre le score en pourcentage, le plus élevé sera le mieux, plaçant Johnny Cage à la première place. Les algorithmes qui étaient des ordres de grandeur plus lents que les autres ont été exécutés sur un sous-ensemble de tests et extrapolés dans le temps. Le propre de C qsort
est inclus pour comparaison (celui de Johnny est plus rapide!). Je ferai une comparaison finale à la fermeture.
Réponses:
150 caractères
Tri rapide.
Comprimé.
la source
150 caractères (sans espaces blancs)
la source
if(*w<*v) { t=v[++l]; v[l]=*w; *w=t; }
peut êtreif(*w<*v) t=v[++l], v[l]=*w, *w=t;
67 7069 caractèresPas rapide du tout, mais incroyablement petit. C'est un hybride entre un tri par sélection et un algorithme de tri par bulles, je suppose. Si vous essayez de lire ceci, vous devez savoir que
++i-v-n
c'est la même chose que++i != v+n
.la source
if(a)b
->a?b:0
enregistre un caractère.++i-v-n
c'est la même chose++i != v+n
que dans un conditionnel, bien sûr.if(*i>v[n])...
->*i>v[n]?...:0
123 caractères (+3 sauts de ligne)
Un tri Shell standard, compressé.
PS: découvert qu'il est toujours 10 fois plus lent que quicksort. Autant ignorer cette entrée.
la source
395 caractères
Tri par fusion.
Formaté.
la source
331326327312 caractèresRadix trie-t-il 8 bits à la fois. Utilise un bithack fantaisie pour obtenir des flottants négatifs pour trier correctement (volé à http://stereopsis.com/radix.html ). Ce n'est pas si compact, mais il est vraiment rapide (~ 8 fois plus rapide que l'entrée préliminaire la plus rapide). J'espère que la taille du code sera plus rapide ...
la source
511424 caractèresRadixsort sur place
Mise à jour: bascule sur le tri par insertion pour les tailles de tableau plus petites (augmente les performances de référence d'un facteur 4,0).
Formaté.
la source
void*
enqsort
(ligne 88) est secouer le pointeur arithmétique.121114111 caractèresJuste un saut de bulles rapide et sale, avec récursivité. Probablement pas très efficace.
Ou, la version longue
la source
221193172 caractèresHeapsort - Pas le plus petit, mais en place et garantit un comportement O (n * log (n)).
Comprimé.
la source
TEST_COUNT
= 3000, il semble échouer au moins un test.154166 caractèresOK, voici un tri rapide plus long mais plus rapide.
Voici une correction pour survivre aux entrées triées. Et formaté car l'espace blanc ne compte pas.
la source
150 caractères
Shellsort (avec écart Knuth).
Formaté.
la source
C 270 (golfé)
Explication: un tableau vide est utilisé pour stocker chaque nombre minimum successif. Un tableau int est un masque avec 0 indiquant que le nombre n'a pas encore été copié. Après avoir obtenu la valeur minimale, un masque = 1 ignore les numéros déjà utilisés. Ensuite, le tableau est recopié dans l'original.
J'ai changé le code pour éliminer l'utilisation des fonctions de bibliothèque.
la source
144
J'ai sans vergogne pris le code de Johnny, ajouté une petite optimisation et compressé le code d'une manière très sale. Il devrait être plus court et plus rapide.
Notez que selon votre compilateur, sort (q, v + n- ++ q) doit être remplacé par sort (++ q, v + nq).
Eh bien, en fait, j'ai commencé à former mon code et à l'optimiser, mais il semble que Johnny ait déjà fait les bons choix. Je me suis donc retrouvé avec quasi son code. Je n'ai pas pensé au truc goto, mais je pourrais m'en passer.
la source
228 caractères
Radixsort.
la source