------------------------------------------------- Exercice 1 ------------------------------------------------- Un exercice simple : il suffit, pour chaque case, de determiner si une case plus a gauche contient la meme valeur (et dans ce cas, de forcer sa valeur a 0). Inutile de traiter les cases deja a 0. void annuler_reps(int *t, int n) { int i, j; for(i = 0; i < n; i++) { if (t[i] == 0) continue; for (j = 0; j < i; j++) if (t[j] == t[i]) { t[i] = 0; break; } } } ------------------------------------------------- Exercice 2 ------------------------------------------------- Le nombre maximal d'occurrences successives d'une valeur parmi toutes les valeurs deja lues est stocke dans kmax. La plus grande valeur apparaissant le plus grand nombre de fois parmi les valeurs deja lues est stockee dans mmax. int max_reps(int *t, int n) { int i, kmax = 1, k = 1, mmax = t[0]; for (i = 1; i < n; i++) { if (t[i-1] == t[i]) { k++; if (k > kmax) { kmax = k; mmax = t[i]; } else k = 1; } return mmax; } ------------------------------------------------- Exercice 3 ------------------------------------------------- On peut, pour cet exercice, utiliser deux drapeaux initialises par exemple au caractere nul, et passant respectivement a la valeur de la premiere voyelle trouvee et a celle de la seconde. (1) lorsque l'on lit une voyelle... (2) si la premiere voyelle n'a pas encore ete trouvee on memorise cette voyelle comme etant la premiere lue, (3) sinon, et si la voyelle courante n'est pas la premiere lue... (4) et si la seconde voyelle n'a pas ete encore lue, on memorise cette seconde voyelle, (5) sinon, et si la voyelle courante n'est ni la premiere, ni la seconde, le texte n'est pas bi-voyellique. (6) en fin de lecture, deux voyelles doivent avoir ete lues - c'est le cas si et seulement si c2 n'est plus a '\0' (avec dans ce cas, c1 necessairement different de '\0'). int bi_voyellique(char *s) { int i; char c1 = '\0', c2 = '\0'; for (i = 0; s[i] != '\0'; i++) { if (s[i] == 'a' || // (1) s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u' || s[i] == 'y') { if (c1 == '\0') // (2) c1 = s[i]; else if (s[i] != c1) { // (3) if (c2 == '\0') // (4) c2 = s[i]; else if (s[i] != c2) // (5) return 0; } } } return c2 != '\0'; // (6) } ------------------------------------------------- Exercice 4 ------------------------------------------------- Un exercice demandant un peu plus de travail d'analyse. Le prefixe commun est forcement prefixe de la toute premiere ligne, on peut donc utiliser la methode suivante. (1) on calcule la longueur de la premiere ligne - elle est stockee dans lp. durant le traitement, lp vaut la taille du plus grand prefixe commun a chacune des lignes deja lues. (2) on se place apres la 1ere ligne. (3) tant qu'il reste des lignes a examiner, (4) on calcule la longueur lpc du plus grand prefixe de longueur au plus lp, commun a la ligne courante et la premiere. (5) on ajuste si necessaire la valeur de lp (6) on se place apres le dernier caractere lu sur la ligne courante, (7) on avance jusqu'au debut de la ligne suivante - ou jusqu'a la fin de la chaine si l'on est sur la derniere ligne. int prefixe_commun(char *s) { int lp, lpc, i; for(lp = 0; s[lp] != '\n'; lp++); // (1) i = lp + 1; // (2) while (s[i] != '\0') { // (3) for (lpc = 0; // (4) lpc <= lp && s[lpc] == s[i + lpc]; lpc++); if (lpc < lp) // (5) lp = lpc; i += lpc; // (6) do // (7) i++; while (s [i - 1] != '\n'); } return lp; } ------------------------------------------------- Exercice 5 ------------------------------------------------- Un seul malloc par chaine d'appel suffit : lorsque l'on atteint la liste vide, on alloue une cellule de clef 0, que l'on renvoie a l'appelant (1). Si la liste est non vide, la compression renvoyee par l'appel recursif (2) contient la somme de toutes les clefs sauf de la premiere. On ajoute celle-ci (3), on libere la premiere cellule (4), et l'on fait suivre la compression a l'appelant (5). struct cell *compresser(struct cell *pc) { struct cell *pnc; if (pc == NULL) { // (1) pnc = malloc(sizeof(struct cell)); pnc -> clef = 0; pnc -> suiv = NULL; return pnc; } pnc = compresser(pc -> suiv); // (2) pnc -> clef = pnc -> clef + pc -> clef; // (3) free (pc); // (4) return pnc; // (5) } ------------------------------------------------- Exercice 6 ------------------------------------------------- Un exercice un peu plus delicat. L'indication centrale etait : on peut modifier temporairement les clefs de pc, pourvu que toutes les cellules soient liberees en fin de traitement. Ceci permet d'eviter les boucles. (1) le deploiement d'une liste vide est vide. (2) les cellules de clef nulle peuvent etre ignorees dans le traitement - on se contente de les liberer. (3) si une cellule est de clef non nulle, il faut une cellule de clef 1 de plus en tete. (4) on fait decroite la premiere clef... (5) et on relance sur la meme liste - mais la recurrence termine, car ceci finit par epuiser la premiere clef de pc. struct cell *deployer(struct cell *pc) { struct cell *qc; if (pc == NULL) // (1) return NULL; if (pc -> clef == 0) { // (2) qc = pc -> suiv; free(pc); return deployer(qc); } qc = malloc(sizeof(struct cell)); // (3) qc -> clef = 1; pc -> clef = pc -> clef - 1; // (4) qc -> suiv = deployer(pc); // (5) } ------------------------------------------------- Casse-tete final ------------------------------------------------- Un exercice assez difficile. (1) on calcule la longueur l de la premiere ligne. si le texte est une echelle, toutes les lignes doivent etre de longueur l. (2) s'il n'y a qu'une seule ligne, on considere par convention que le texte est une echelle de rang nul. sinon, (3) on se place au debut du texte. (4) tant qu'il reste au moins deux lignes, (5) on compare la ligne courante et la ligne suivante en parallele : - (6) la ligne suivante ne doit pas etre plus courte que la ligne courante, - (7) on compte les differences entre les deux lignes. (8) la ligne suivante ne doit pas etre plus longue que la ligne courante. (9) si aucun rang n'est encore determine, le rang candidat est le premier nombre de differences calcule. (10) sinon, et s'il n'y pas le meme nombre de differences qu'aux etapes precedentes, le texte n'est pas une echelle. int degre_echelle(char *s) { int l, i, rang = -1, diff; for (ll = 0; s[l] != '\n'; l++); // (1) if (s[l + 1] == '\n') // (2) return 0; i = 0; // (3) while(s[i + l + 1] != '\0') { // (4) diff = 0; while(s[i] != '\n') { // (5) if (s[i + l + 1] == '\n') // (6) return -1; if (s[i] != s[i + l + 1]) { // (7) diff++ ; } i++; } if (s[i + l + 1] != '\n') // (8) return -1; if (rang < 0) // (9) rang = diff; else if (rang != diff) // (10) return -1; i++; } return rang; } -------------------------------------------------