une balle, un imp (Newstuff #491, Edge, Duke it out in Doom, John Romero, DoomeD again)
Canard zizique : q 4, c, d, c, g, n , t-s, l, d, s, r, t, d, s, c, jv, c, g, b, p, b, m, c, 8 b, a, a-g, b, BOF, BOJV, c, c, c, c, e, e 80, e b, é, e, f, f, f, h r, i, J, j, m-u, m, m s, n, o, p, p-r, p, r, r r, r, r p, s, s d, t, t
Canard lecture
Après, y'a pire. Dans un langage que j'utilise, les tableaux commencent parfois à 1, parfois à 0. D'ailleurs parfois false=-1 et parfois false=0
C'est implémenté en python et pas en C (au contraire du dict classique et de la list) donc les perfs sont plus faibles que le dict anyway.
Code:def __setitem__(self, key, value, dict_setitem=dict.__setitem__): 'od.__setitem__(i, y) <==> od[i]=y' # Setting a new item creates a new link at the end of the linked list, # and the inherited dictionary is updated with the new key/value pair. if key not in self: root = self.__root last = root[0] last[1] = root[0] = self.__map[key] = [last, root, key] return dict_setitem(self, key, value)
Faisons la paix et coupons la poire en deux en suivant l'exemple des programmeurs graphiques. Le premier texel est à la coordonnée 0,5, le deuxième à 1,5, le troisième à 2,5, et ainsi de suite. Problème résolu.
Ca me rappelle ces travaux sur la topologie qui définissaient un espace spéciale pour qu'une sélection de voxels soit un contour qui passe exactement 'entre' les voxels internes et externes.
Tiens, à propos de tableaux...
En C++11, y'a pas un itérateur du genre
qui afficherait les entiers de 0 à 4 (ou 1 à 5 ) ?Code:for (size_t i : 0 : 5) cout << i
Bref, un truc qui serait aussi facile que le parcours d'un conteneur avec for(const auto &bin : conteneur) ?
En lisp, on a bien iota pour ce genre de bêtises.
std::iota existe en C++, mais il remplit un tableau, c'est un peu du gaspillage de mémoire. Tu peux créer ton propre itérateur si écrire "for (size_t i = 0; i <=5; ++i)" te dérange tant.
La fonction iota en Scheme est analogue à celle du C++, elle crée une liste composée de toutes les valeurs, ce n'est pas un itérateur. Donc gaspillage inutile de mémoire comme l'indique Cwningen.
En Common Lisp, tu fais un dotimes ou un loop (voir iterate pour avoir un truc plus propre). Et si la gestion des bornes te casse les pieds, tu fais une macro.
Rien ne me choque moi, je suis un scientifique ! - I. Jones
J'ai essayé d'écrire l'itérateur pour voir : https://gcc.godbolt.org/z/eGPOrb. La fin boucle est un peu chiante à écrire à cause de l'opérateur != utilisé au lieu de <= (et je ne suis même pas trop sûr de ce que j'ai écrit). Je sais pas si quelqu'un a une astuce pour faire mieux. Dans le cas constexpr, ça n'a pas l'air trop catastrophique pour l'assembleur généré.
Boucle traditionnelle :
Boucle avec itérateur :Code:movl $-3, %r14d .LBB0_1: addl $3, %r14d ... intérieur de la boucle ... cmpl $8, %r14d jl .LBB0_1
J'imagine que le changement d'ordre de la boucle traditionnelle est là mieux remplir le pipeline (mieux séparer l'addition et la comparaison).Code:xorl %r14d, %r14d .LBB0_7: ... intérieur de la boucle ... addl $3, %r14d cmpl $12, %r14d jne .LBB0_7
Je vous poste un petit example de code sympa () trouvé dans mon cher projet C pour faire une petite revue de code.
J'ai peut-être glissé des erreurs en anonymisant la bête:
Les structures utilisés:
L'algo:Code:/* structure avec plein de champs*/ struct Aggregate { char* champ1; // ou champ0 au choix ;) ... char* champN; ... char* champItemA[]; char* champItemB[]; ... char* champItemZ[]; /* 13 champItem au total */ } struc SortItem { char* champItemA; char* champItemB; ... char* champItemZ; /* 13 champs au total, oui, les même que dans Aggregate */ }
Code:Aggregate aggregate; grosseFunctionAvecDuSqlPourRemplir(&aggregate); SortItem sortItem; sort = 1; j = nbItem; while (sort) { sort = 0; for (i = 0; i < j; i++) { d = compareField (item.fieldX[i], item->fieldX[i+1]); if ((d < 0) || ((d == 0) && (compareField (item->fieldY[i], item->fieldY[i+1]) < 0))) { memset ((char *)&sortItem, 0, sizeof (sortItem)); k = i + 1; strcpy(sortItem.fieldA, aggregate->fieldA[i]); ... /* il y a 13 champs */ strcpy(sortItem.fieldZ, aggregate->fieldZ[i]); strcpy(aggregate.fieldA[i], aggregate->fieldA[k]); ... /* il y a 13 champs */ strcpy(aggregate.fieldZ[i], aggregate->fieldZ[k]); strcpy(aggregate.fieldA[k], sortItem->fieldA); ... /* il y a 13 champs */ strcpy(aggregate.fieldA[i], sortItem->fieldZ); sort = 1; } } }
Tu as oublié du code ou ça plante au premier strcpy (la chaine de destination n'est pas allouée) ? En dehors des problèmes de copies de chaines, c'est censé faire quoi ? Une sorte de tri partiel ? Je comprends pas la variable sort.
PS: S'il y a 13 champs, ça va de A à M. Sauf si tu commences par numéroter à B.
Cwningen, tu ne connais pas encore l'art de l'ellipse et du pseudo-code...
Je n'allais pas copier coller directement du code d'entreprise, très verbeux qui plus est.
Ici c'est l'algo qui est amusant.
Oui, c'est un tri à bulle. Avec recopie de tous les champs à chaque swap.
Dernière modification par William Vaurien ; 28/09/2018 à 21h15.
C'est juste pour être sûr, tu as bien pris la peine de mettre le memset. Mais il y a bien plein de malloc (3 fois 13 ?) à chaque itération, c'est ça ? Pas de tableau réutilisé ?
Et en relisant une deuxième fois, je vois que je m'étais embrouillé avec sort, c'est bien un tri complet (quadratique de la pire sorte, une sorte de tri bulle mal fait).
C'est très KIS en fait. Reste à savoir si c'est le Simple ou le Stupid qui manque...
Il n'y a aucun intérêt à faire ça, en entreprise ou ailleurs et je ne sais pas si c'est vraiment le tri à bulles le pire... Pour moi c'est plutôt ces structures dégueulasse et les recopies de valeurs...
Pour la mémoire elle est toujours dans le code à taille fixe, ce sont des tableaux de tableaux sous cette forme :
char tableau[MAX_ARR_LEN] [MX_STR_LEN]
Le test x < 0 || x == 0 à de la gueule aussi..
Ba les structures et les recopies de valeurs, effectivement, c'est pas beau. Et du coup pas tres "simple"
En tout cas, si le tri a bulles est le plus lent. Apres, c'est justement le plus simple a implementer, ce qui fait encore plus de peine de voir ce genre de code etre utilise, puisque tu n'as ni la simplicite, ni la rapidite.
Il y a plus lent, le bogosort.
une balle, un imp (Newstuff #491, Edge, Duke it out in Doom, John Romero, DoomeD again)
Canard zizique : q 4, c, d, c, g, n , t-s, l, d, s, r, t, d, s, c, jv, c, g, b, p, b, m, c, 8 b, a, a-g, b, BOF, BOJV, c, c, c, c, e, e 80, e b, é, e, f, f, f, h r, i, J, j, m-u, m, m s, n, o, p, p-r, p, r, r r, r, r p, s, s d, t, t
Canard lecture
Les dictionnaires ordonnés de Python, ils sont ordonnés par l'ordre d'insertion, pas par un ordre a priori des clés. Donc je suppose que c'est implémenté par une table de hachage avec chaînage des objets, ou double indirection. L'accès via clé devrait donc être dominé par le calcul de la fonction de hachage.
Si ce sont des tableaux et non des pointeurs, on est bien obligé de copier toutes les chaines puisqu'on ne peut pas simplement échanger les pointeurs. Le problème c'est la structure de données, pas les strcpy eux-mêmes.
Là t'es malhonnête, il y a des parenthèses importantes. Je ne vois rien de mal dans ce test là.
Il y a un && après le == 0 pour envoyer une deuxième condition, donc non tu peux pas <=
Bien vu, j'étais passé complètement par dessus.