Vous êtes sur la page 1sur 21

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

retour

Algorithmique pratique et optimisation de code : les liminatoires du Prologin dition 2005

1 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

Notice
Le prsent document est publi sous la licence Verbatim Copying telle que dnie par la Free Software Fondation dans le cadre du projet GNU. Toute copie ou diusion de ce document dans son intgralit est permise (et mme encourage), quel qu'en soit le support la seule condition que cette notice, incluant les copyrights, soit prserve. Copyright (C) 2005 Yann LANGLAIS, ilay. PROLOGIN est une association loi 1901 visant permettre de jeunes passions d'informatique de se rencontrer pour se mesurer entre eux et de faciliter les changes d'ides. Elle organise tous les ans le Concours National d'Informatique. Elle est parainne par le Ministre dlgu la Recherche et aux Nouvelles Technologies, et sponsorise par l'Epita, Hexaglobe et les magazines PCTeam et Login:. La plus rcente version en date de ce document est sise l'url http://ilay.org /yann/articles/prologin2005/. Toute remarque, suggestion ou correction est bienvenue et peut tre adresse Yann LANGLAIS, ilay.org.

2 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

Introduction
L'preuve d'algorithmique des liminatoires du Prologin est toujours un rgal. Pour tous les curieux qui, comme moi sont [beaucoup ?] trop vieux pour participer, c'est l'occasion de redmarrer la machine penser et de vrier que les engrenages [diodes ? transistors ?] ne se sont pas trop encrasss et tournent toujours rond. Au del du d, et comme le dit si bien l'accroche du concours, c'est l'occasion de dcouvrir ou de redcouvrir des terres oublies. A l'instar des prcdentes ditions, je m'y suis jet comme un gamin. Mais, cette fois, j'ai dcid de poser sur le papier mes rexions et de vous inviter les partager.

3 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

O nous comptons les bits


Enonc
1. crire une fonction qui prend un entier positif en argument (infrieur 1000) et retourne le nombre d'occurrences du chire 1 dans la reprsentation binaire naturelle de cet entier. Exemple : On passe 42 la fonction, elle doit retourner 3, puisqu'en binaire, 42 s'crit 101010.

Conception
Reevons-nous vraiment un entier en paramtre? De prime abord, la question peut paratre saugrenue. Cependant, si l'on a un entier, habituellement reprsent en dcimal, il nous faut obligatoirement le convertir en binaire an de rpondre la question. Or, le paramtre que nous reevons est un entier cod en binaire, l'ordinateur ne comprenant que le codage binaire (hormis le BCD, ou Binary Coded Decimal, utilis par les bibliothques de calcul dites prcision arbitraire ). Nous recevons donc du binaire et il nous sut de parcourir une liste de bits. Si le bit courant est 1, il nous faut incrmenter un compteur entier (cod lui aussi en binaire). En premire approximation, l'ordre de l'algorithme ne devrait pas dpasser o(n) o n est le nombre de digits sur lequel est cod l'entier. Le nombre d'itrations ne devrait ainsi pas dpasser 10 (la 10-ime puissance de 2 vaut 1024, qui est suprieur notre limite de 1000).

Implmentation
Nous avons un trs grand nombre de possibilits an d'implmenter cette recette. Nous pouvons utiliser l'oprateur & binaire, ou encore le reste d'une division entire par 2. Nous pouvons utiliser une variable ltre qui sera multiplie par 2 chaque itration, ou encore diviser par 2 notre entier pass en paramtre (pour peu que celui-ci ne soit pas pass en tant que const). An de faire l'conomie d'une variable, je choisis d'utiliser notre paramtre ( value).
1. J'initialise mon compteur 0. 2. Tant que value n'est pas nul 2.1 Je teste si son bit de poids faible est 1 (ET binaire). 2.1.1 Si c'est le cas, alors j'incrmente le compteur. 2.2 Je dcale les bits de value d'un cran vers la droite 3. je retourne mon compteur.

Voyons ce qui ce passe avec l'exemple fourni par l'nonc :


count value value value value = 0; = 42 & 1 >>= 1 & 1 --> --> --> --> 101010 0 010101 1 initialisation de count 0 value vaut 101010 le premier bit est-il 1 ? non. on dcale vers la droite d'1 bit le premier bit est il 1 ? oui,

4 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005


==> count <-- 1 ...

http://ilay.org/yann/articles/prologin2005/
alors on incrmente count

Voici l'implmentation en C :
/* * Retourne le nombre de bits 1 dans la reprsentation binaire * de d'un entier compris entre 0 et 1000, ou -1 si l'entier n'est * pas dans l'intervalle : */ int prg1(int value) { int count = 0; /* On vrifie que le paramtre est dans les limites : */ if (value < 0 || value >= 1000) return -1; /* puis on compte les digits 1 : */ while (value) { if (value & 1) count++; value >>= 1; } return count; }

Discussion
D'une faon gnrale, il est dicile de simplier d'avantage ces lignes, tant en terme de trace mmoire que de performances. Les direntes optimisations possibles de cette fonction dpendantes de la plateforme, du processeur et du compilateur. sont largement

On pourra commencer par dclarer les variables value et count en tant que register. Pour le reste, il faudra eectuer des tests en remplaant & par % 2 ou encore >>= 1 par /2. Il faudra aussi jouer avec les options de compilation, voire, comparer les dirents dsassemblages des excutables gnrs. Mais dans tous les cas de gure, les gains de performances resteront assez limits.

5 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

O nous comptons les carts


Enonc
2. On vous donne un tableau de N entiers positifs distincts et un entier K, o N et K sont compris entre 1 et 1000. Ecrire une fonction prenant en argument ce tableau et ces entiers et retournant le nombre de couples de nombres qu'il est possible de former en conservant une distance infrieure ou gale K dans chacun des couples. Exemple : On dispose de la liste 10 1 21 7 16 9 12 18 4 19 (N = 10), et on donne K = 2. Alors on peut former les couples suivants : (7,9), (9,10), (10,12), (16,18), (18,19) et (19, 21). La fonction retourne donc 6.

Conception
Ce second problme requiert le calcul des carts entre toutes les paires d'entiers. L'ordre de l'algorithme est donc Cn2 = n (n - 1) / 2, soit le cardinal des possibilits du tirage de 2 nombres parmi n, o n est le nombre d'lments du tableau. Donc, pour eectuer nos n (n - 1) / 2 tests, on utilisera deux boucles imbriques. La premire, indice par i, parcourt les n - 1 premiers termes (de 0 n - 2 et la seconde, indice par j, parcourt les lments de i + 1 n - 1. Pour tous les couples (i, j) ainsi constitus, on calcule abs(N[i] - N[j]). Si cette valeur est infrieure ou gale k, alors on incrmente notre compteur.

Implmentation
/* * Fonction d'aide retournant la valeur absolue d'un entier : */ int abs(int a) { if (a < 0) return -a; return a; } /* * Retourne le nombre de paires dont l'cart est infrieur ou gal k * ou -1 si n ou k ne sont pas des valeurs correctes, * ou -2 si N n'est pas dfini : */ int prg2(int n, int *N, int k) { int i, j, c = 0; /* Vrifie que k et n sont correctes */ if (k < 1 || k > 1000 || n < 1 || n > 1000) return -1; /* Vrifie que le tableau d'entier n'est pas un pointeur nul : */ if (!N) return -2;

6 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

for (i = 0; i < n - 1; i++) for (j = i + 1; j < n; j++) if (abs(N[i] - N[j])) c++; return c; }

Discussion
Cette fois-ci encore, il est dicile de simplier ( moins d'une ide lumineuse de conception). On peut encore jouer avec les directives de compilation, dnir les variables locales comme register (au cas o a ne soit pas fait automatiquement) et dnir la fonction abs comme inline. On pourra aussi utiliser une expression ternaire comme :
#define abs_diff(A, B) ((A) > (B) ? ((A) - (B)) : ((B) - (A)))

7 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

O nous testons la symtrie


Enonc
3. Ecrire une fonction qui prend en argument une matrice remplie de 0 et de 1 contenant une forme gomtrique, et deux entiers L et C qui sont respectivement le nombre de lignes et de colonnes compris entre 1 et 1000 inclus. La fonction devra renvoyer 1 s'il existe un axe de symtrie vertical sur la gure forme par l'ensemble des chires 1, 0 sinon. Exemples :
La forme L=3, C=6 0 0 1 1 0 0 0 1 1 1 1 0 0 0 1 1 0 0 0 1 0 0 1 1 1 0 1 1 1 0 est symtrique selon l'axe vertical. Le rsultat est donc 1.

La forme L=3, C=4

est aussi symtrique selon l'axe vertical. On retourne 1.

Conception
Des dirents algorithmes proposs, celui-ci est le plus dicile mettre en oeuvre. Commencons par simplier l'nonc en considrant le cas d'une matrice possdant un axe de symtrie vertical en son centre. Dterminer si une matrice comporte un axe de symtrie revient vrier si chaque ligne est symtrique, i.e. est un palindrome. Cette opration est eectue en parcourant une ligne simultanment par ses deux extrmits jusqu' son centre en testant l'galit des lements i et n - i - 1, pour tout i allant de 0 n - 1 . Prouver qu'une matrice est symtrique ncessite de tester tous ses composants deux deux. A contrario, la premire rupture de symtrie qui se prsentera sura prouver que la matrice n'est pas symtrique. Le pire des cas survient donc lorsque la matrice est symtrique car nous devons alors tester toutes les colonnes de toutes les lignes. Notre algorithme est, en premire approximation et dans le pire des cas, de l'ordre de n / 2.
0 0 1 1 0 0 1 1 0 0 ^ ^ a[0] == a[n - 1] ? 0 0 1 1 0 0 1 1 0 0 ^ ^ a[1] == a[n - 2] ? 0 0 1 1 0 0 1 1 0 0 ^ ^ a[2] == a[n - 3] ? ... jusqu'au centre de la ligne

Nous n'avons cependant pas rpondu la question. En eet, nous avons suppos que l'axe se trouvait au milieu de chaque ligne, ce qui est invalid par le second exemple. Bien que ce procd ne soit en gnral pas une bonne ide, car il vaut

8 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

mieux prvoir (prvenir) que patcher (gurir), nous pouvons conserver notre premire approche et y apporter des corrections. Il faut ajouter deux corrections de premier ordre notre dmarche : il faut se positionner sur le premier et le dernier 1 de chaque ligne avant de vrier qu'elle est symtrique, il faut s'assurer que l'axe de symtrie est invariant de ligne en ligne. Le premier point est gr par deux boucles conscutives de recherche du premier et dernier 1 de chaque ligne. Le second se fait en sauvant la position droite et gauche de l'axe de symtrie puis en les comparant aux valeurs pour la ligne suivante.
0 0 0 0 1 1 0 1 1 0 0 ^ | ^ --> 1 1 0 1 1 ^ | ^ axe

0 0 0 1 0 1 0 1 0 1 0 ^ | ^

-->

1 0 1 0 1 0 1 ^ | ^ axe

Cette seconde correction ncessite une correction de second ordre (eet secondaire d'une correction de premier ordre). En eet, si une ligne vide (i.e. dont toutes les colonnes sont 0) se prsente, il faut s'assurer qu'elle n'inue pas sur la dernire position de l'axe. Comme une ligne vide est neutre vis vis de la symtrie, le plus simple est d'ignorer purement et simplement et de passer la ligne suivante. Nous devons encore nous poser une ultime question : Est-ce qu'une matrice dont tous les lments sont nuls possde un axe de symtrie ? Ce point n'tant pas dtermin par l'nonc, j'ai choisi de rpondre par l'armative.

Implmentation

9 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

/* * Retourne 1 si la matrice possde un axe de symtrie, 0, si non, * En cas d'erreur, retourne : * -1 si L ou C hors limite, * -2 si la matrice n'est pas alloue, * -n si la (n - 2)-ime ligne n'est pas alloue. */ int prg3(int L, int C, int **mat) { int l, i, j; int lasti = -1, lastj = -1; /* Test des paramtres L et C : */ if (L < 1 || L > 1000 || C < 1 || C > 1000) return -1; /* Test de la matrice d'entre : */ if (!mat) return -1; /* Boucle sur toute les lignes : */ for (l = 0; l < L; l++) { /* Test de la ligne en cours : */ if (!mat[l]) return -(2 + l); /* Trouver le 1er 1 gauche : */ for (i = 0; i < C && !mat[l][i]; i++); /* Si pas de 1, on explore la ligne suivante : */ if (i == C) continue; /* Trouver le 1er 1 droite : */ for (j = C - 1; j >= i && !mat[l][j]; j--); /* Vrifier la symtrie entre les premiers 1 droite et gauche : */ while (i < j) { /* Si rupture de symtrie => retourner 0 : */ if (mat[l][i] != mat[l][j]) return 0; i++, j--; } /* Vrifie l'unicit de l'axe de symtrie : */ if (lasti > -1 && (lasti != i || lastj != j)) /* Axe diffrent => retour 0 : */ return 0; /* Sauver la position de l'axe de symtrie : */ lasti = i, lastj = j; } /* La matrice est symtrique : */ return 1; }

Discussion

10 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

Nos corrections ont ajout des itrations supplmentaires par rapport au problme de base. Le pire des cas est maintenant celui o la matrice est nulle. On parcourt alors toute la matrice la recherche d'un 1. Dans le cas d'une matrice symtrique o les premires et dernires colonnes sont 1, nous retrouvons le pire cas du problme de base avec tout juste n / 2 itrations. Notons que lasti et lastj ne contiennent pas respectivement la dernire colonne avant et la premire colonne aprs l'axe de symtrie, mais exactement le contraire, ce qui ne fait pour nous aucune dirence. Comme il est crit plus haut, il est prfrable, dans le cas gnral, d'viter de rpondre un problme en terme de patches d'une solution un problme plus simple. Ce cas est un bon contre exemple conrmant que le dogme doit s'eacer devant le pragmatisme. Il est, par contre, ncessaire d'tre exhaustif dans la prise en compte des eets secondaires que chaque retouche apporte.

11 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

O nous jouons avec la lumire


Nous allons nous arrter un peu plus longtemps sur ce sujet car il illustre bien les implications de la faon d'apprehender un problme donn sur le code (et ses performances).

Enonc
4. Pour une rampe de P projecteurs, un clairagiste a install quatre interrupteurs ayant un eet dirent : L'interrupteur 1 inverse l'tat de tous les projecteurs de la rampe. L'interrupteur 2 inverse l'tat des projecteurs portant un numro pair. L'interrupteur 3 inverse l'tat des projecteurs portant un numro impair. L'interrupteur 4 inverse l'tat des projecteurs dont le numro est de la forme 3K + 1, o K est un entier. Au dpart, tous les projecteurs sont teints. L'clairagiste factieux dcide de presser un nombre B de boutons au hasard. Vous devez crire une fonction qui prend trois arguments : Un entier P (avec 0 < P < 1001) reprsentant le nombre de projecteurs. Un entier B (avec 0 < B < 100001) reprsentant le nombre de boutons presss par l'clairagiste. Un tableau de taille B contenant des entiers compris entre 1 et 4 qui reprsentent, dans l'ordre, les interrupteurs que l'clairagiste a presss (on identie le premier projecteur comme le projecteur 1). Votre fonction doit acher une chane compose de 0 et de 1, de longueur P qui reprsente l'tat nal de la rampe de projecteurs aprs l'intervention de l'clairagiste : le chire 1 reprsente un projecteur allum, et le chire 0 un projecteur teint. Exemple :
Soit P = 4, B = 3, et les tats des interrupteurs conformes au tableau : [1, 2, 4] On obtient l'ordre suivant : 0000 1111 1010 On retourne donc le rsultat : 0011

Conception

Ce problme peut tre abord sous des angles dirents. En premier lieu, nous verrons une approche physique . Nous discuterons aussi des direntes
12 sur 21 22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

possibilits de l'implmenter. Puis nous verrons ce que peuvent nous apporter quelques notions mathmatiques de base. Enn, nous comparerons les direntes approches ainsi que leur ecacic respective.

Approche physique
Nous allons commencer par une approche physique en reprenant l'nonc tel quel. On a p projecteurs et b boutons. Intuitivement, notre algorithme sera de l'ordre de p * b. En eet, l'tat de chaque projecteur dpend de la squence des boutons. Dans cette hypothse, on utilise 2 boucles imbriques. L'une pour les projecteurs, et l'autre pour les boutons. L'ordre d'imbrication inue sur le code. En eet, si la boucle externe se charge de parcourir les projecteurs, on aura toujours au total p * b itrations, mais on pourra acher l'tat des projecteurs en cours de calcul. Si l'on inverse l'ordre des boucles, on pourra ne parcourir que les projecteurs de la suite correspondant au bouton en cours : tous si bouton 1, un sur deux pour les 2 et 3, seulement un sur trois pour le 4. Les 4 boutons tant quiprobables, on aura (o p est ne nombre de projecteurs) : Probabilit nb d'itrations bouton 1 bouton 2 bouton 3 bouton 4 1/4 1/4 1/4 1/4 p p/2 p/2 p/3

Le temps moyen (ou nombre d'itrations moyen) par bouton sera donc de l'ordre de :
p . (1/4 + 1/2 . 1/4 + 1/2 . 1/4 + 1/3 * 1/4) ~ 0.58 p

soit en moyenne environ 40% d'itrations en moins par rapport au cas prcdent. Nous aurons au pire p * b itrations. Par contre, cet agencement nous oblige conserver l'tat de tous les projecteurs en permanence et donc rserver un espace mmoire cet eet, et, comme nous ne sommes pas certains que la dernire boucle passe par tous les projecteurs, il est ncessaire d'eectuer une boucle supplmentaire ddie l'achage de l'tat des projecteurs. Notre pire cas devient donc p * (b + 1). ll sera en moyenne plus rapide que le prcdent d'environ 40%, mais consommera un peu plus de mmoire. Nous verrons ces deux approches dans la phase d'implmentation.

Approche mathmatique
Voyons ce que donne une approche plus mathmatique . Chaque bouton peut, tout comme notre srie de projecteur, tre assimil une suite. L'activation d'un bouton dclenche une opration xor entre la suite reprsentant l'tat de nos projecteurs et la suite reprsentative du bouton activ. Nous avons les suites, qui contrairement ce qui est stipul dans l'nonc,

13 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

commencent ici 0 :
s0 s1 s2 s3 s4

qui reprsente l'tat initial, le bouton 1 (111111...) le bouton 2 (101010...) le bouton 3 (010101...) le bouton 4 (010010...)

On remarque que s0 est l'inverse de s1 et s2, l'inverse de s3. En jouant avec xor, on voit apparatre certaines proprits :
s0 s1

agit comme un lment neutre car s0 xor si = si xor s0 = si agit comme un inverseur

Ces proprits rappellent celle d'une base dont l'oprateur multiplication est ici xor. Cependant, cette base n'est pas complte. Il nous manque tout d'abord l'inverse de s4. Celui-ci s'obtient par l'opration s4 xor s1. On note cet inverse s5 (101101...).
010010... s4 xor 111111... s1 --------------101101... s5

Le fait d'avoir une base est intressant car nous pourrons peut-tre en dduire un certain nombre de proprits contraignant notre oprateur. Lorsque l'on eectue l'opration s2 xor s4, on obtient une nouvelle suite (111000...). Nommons la s6. s6 doit aussi avoir un inverse (s6 xor s1), s7 (000111...). Et, l, surprise, notre base est complte! Quels que soient les oprandes, notre oprateur xor donne un rsultat appartenant notre base :
101010... s2 xor 010010... s4 ------------111000... s6 101010... s2 xor 111000... s6 ------------010010... s4 010010... s4 xor 111000... s6 ------------101010... s2

Il en va de mme avec les suites ngatives


xor i),

Notre base est un groupe ni. Et comme l'oprateur xor est commutatif (i xor j = j ce groupe est ablien.

Ces considrations mathmatiques ont des implications non-ngligeables sur notre problme. D'une part, comme le groupe est ni et ne contient que 8 lments, toute combinaison de boutons donnera une de ces 8 suites. D'autre part, l'existence d'une table de multiplication permet de compiler la liste des boutons une fois pour toutes pour obtenir directement l'tat nal de notre rampe de projecteurs. Voici cette table : bouton s0 s1 s2 s3 s4 s5 s6 s7

14 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

s0 s1 s2 s3 tat s4 s5 s6 s7

s0 s1 s2 s3 s4 s5 s6 s7

s1 s0 s3 s2 s5 s4 s7 s6

s2 s3 s0 s1 s6 s7 s4 s5

s3 s2 s1 s0 s7 s6 s5 s4

s4 s5 s6 s7 s0 s1 s2 s3

s5 s4 s7 s6 s1 s0 s3 s2

s6 s7 s4 s5 s2 s3 s0 s1

s7 s6 s5 s4 s3 s2 s1 s0

L'algorithme qui en dcoule comporte donc deux parties : La premire eectue l'opration spcie dans notre tableau de boutons. La seconde ache l'tat des projecteurs. Nous avons toujours deux boucles, mais elles ne sont plus imbriques. L'ordre se rduit alors p + b.

Implmentation Approche physique


Nous allons implmenter les deux types d'imbrications des ns comparatives. Il n'y a dans les deux cas, aucune dicult notable. Boucle externe sur les projecteurs Pour chaque projecteur, nous initialisons 0, puis, pour chaque bouton, nous vrions si le bouton en cours modie l'tat du projecteur. Si c'est le cas, nous inversons l'tat du projecteur.
void prg4_1(int p, int b, int *B) { int i, j, val; /* Boucle externe sur les projecteurs : */ for (i = 1; i <= p; i++) { /* Initialisation du projecteur : */ val = 0; /* Boucle interne sur les boutons : */ for (j = 0; j < b; j++) /* Est-ce que le bouton modifie l'tat du projecteur? : */ if ( B[j] == 1 || (B[j] == 2 && !(i % 2)) || (B[j] == 3 && (i % 2)) ||

15 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005


(B[j] == 4 && !((i - 1) % 3))) /* Change l'tat du projecteur : */ val ^= 1; /* Affiche l'tat du projecteur : */ putchar(val + '0'); } putchar('\n'); }

http://ilay.org/yann/articles/prologin2005/

Boucle externe sur les boutons


void prg4_2(int p, int b, int *B) { int i, j; /* Dfinition des suite d'aprs leur premier lment : */ int start[5] = {0, 1, 2, 1, 1}; /* et d'aprs l'incrment pour l'lment suivant : */ int incr[5] = {0, 1, 2, 2, 3}; /* mmoire pour les projecteurs : */ int prj[1002]; /* initialise les projecteurs 0 : */ memset((void *) (prj + 1), 0, p * sizeof(int)); /* boucle externe sur les boutons : */ for (j = 0; j < b; j++) { /* boucle externe sur les projecteurs : */ for (i = start[B[j]]; i <= p; i += incr[B[j]]) { /* inversion du projecteur : */ if (prj[i]) prj[i] = 0; else prj[i] = 1; } } /* Affichage des projecteurs : */ for (i = 1; i <= p; i++) putchar(prj[i] + '0'); putchar('\n'); }

Approche mathmatique
Les deux points fondamentaux de l'implmentation sont le codage de la table de multiplication et de la gnration de la suite nale. La table complte comporte 64 entres. Cependant, comme nous ne possdons que quatre boutons, nous n'avons besoin que de la moiti des colonnes (s1, s2, s3 et s4), soit 32 entres (colonnes en jaune sur la table de multiplication). On utilisera un accumulateur , la variable acc, charg de contenir le membre gauche de notre opration en cours. Il sert d'index de ligne. L'index de colonne est lui reprsent par le numro du bouton en cours, diminu de 1. Le rsultat, table[acc][B[i] - 1] est lui mme aect acc. Une fois tous les boutons parcourus, acc ne contient rien

16 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

de moins que le numro de la suite nale. L'achage de la suite nale peut tre fait de plusieurs manires. On peut, partir de la dnition mathmatique de chaque suite, vrier si le numro du projecteur en cours rpond aux critres de la suite. L'implmentation ncessite alors d'eectuer des tests. Sur ce point, j'ai opt pour une reprsentation plus informatique : je code le motif minimal commun de chaque suite dans un tableau. Aussi le i-me lment sera donn par un calcul sur pointeurs. Le motif le plus long est celui des suites s6 et s7 et fait 6 bits. Aussi, le notre i-me lment est donn par suite[acc][i % 6].
void prg4_3(int p, int b, int *B) { /* Table de multiplication : */ int table[8][4] = { {1, 2, 3, 4}, {0, 3, 2, 5}, {3, 0, 1, 6}, {2, 1, 0, 7}, {5, 6, 7, 0}, {4, 7, 6, 1}, {7, 4, 5, 2}, {6, 5, 4, 3} }; /* Codage du motif des 8 suites : */ int suite[8][6] = { {0, 0, 0, 0, 0, 0}, {1, 1, 1, 1, 1, 1}, {1, 0, 1, 0, 1, 0}, {0, 1, 0, 1, 0, 1}, {0, 1, 0, 0, 1, 0}, {1, 0, 1, 1, 0, 1}, {1, 1, 1, 0, 0, 0}, {0, 0, 0, 1, 1, 1} }; /* Accumulateur 0 : */ int acc = 0, i; /* Calcul de la suite */ for (i = 0; i < b; i++) acc = table[acc][B[i] - 1]; /* Affichage de la suite de projecteurs : */ for (i = 1; i <= p; i++) putchar(suite[acc][i % 6] + '0'); putchar('\n'); }

Discussion
Un petit test comparatif s'impose. Les trois fonctions ont t incluses dans un mme chier. On gnre alatoirement une squence de 1000 boutons qui vont oprer sur 1000 projecteurs. Comme les temps sont trs petits et pour minimiser l'impact de la charge machine, les fonctions sont appeles 1000 fois d'ale avec les mmes paramtres. On chronomtre le temps total de ces 1000 itrations, boucle incluse (pour plus d'informations, consulter les chiers prg4.c et coverage.c). Le rsultat est pour le moins diant :
17 sur 21 22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

algorithme prg4_1 prg4_2 prg4_3

Solaris cc 22.004618 5.292302 0.046198

Solaris gcc 15.226231 5.481149 0.083301

Linux gcc 19.592074 4.090236 0.164511

Conditions de test: Ce test a t eectu sur plateforme Sun : SunOS 5.8 Generic_117350-13 sun4u sparc SUNW,Sun-Fire-880 avec cc WS6U2 et gcc 2.95.2. Sur plateforme Linux : Fedora 3 2.6.9-1.667 i686 athlon i386 GNU/Linux avec gcc 3.4.2 Les rapports des temps entres les dirents algorithmes sur une mme plateforme sont assez diants. La dirences d'agencement des boucles imbriques est d'un facteur 4 en moyenne (prg4_2 dpend, comme nous l'avons vu, de la qualit des donnes). Ce facteur est dj loin d'tre ngligeable. Mais la dirence la plus importante provient des direntes approches d'un mme problme. Le facteur est dans ce cas de l'ordre de plusieurs dizaines de prg4_2 prg4_3 et de la centaine de prg4_1 prg4_3.

18 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

Conclusion
Cette preuve des liminatoires du Prologin 2005 nous a permis d'entrevoir direntes mthodes de rexion concernant l'laboration d'algorithmes. Nous avons aussi pu observer les eets de quelques unes des approches possibles. Si certains sont minimes, d'autres ont des implications profondes sur les performances. Comme il n'y a jamais qu'une seule et unique faon de faire les choses, il est bien vident que les solutions vues ici ne sont pas forcment les meilleures. Je vous invite donc me faire part de toutes vos remarques l'adresse suivante ylanglais@gmail.com. Si celles-ci sont nombreuses et intressantes, je me ferais une joie de les inclure ce prsent document.

19 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

Code source
Voici le code des dirents programmes et outils utiliss dans l'article.

20 sur 21

22/01/2013 23:01

Eliminatoires Prologin 2005

http://ilay.org/yann/articles/prologin2005/

Rfrences
Prologin: Le site ociel Mathmatiques: dnition d'un groupe Algorithmique pratique et optimisation de code : La gnration de labyrinthes

Cet article est paru dans Login: n128, mai 2005

21 sur 21

22/01/2013 23:01

Vous aimerez peut-être aussi