Quelques indication de corrections, en attendant les notes definitives. Le niveau des copies est, a seulement deux exceptions pres, tres faible. ---------- Exercice 1 ---------- Cet exercice a ete totalement incompris. Le tableau t est obtenu par collage dans u s'il est possible de decouper t en deux parties : un prefixe de u, suivi d'un suffixe de u. (1) on cherche le plus grand prefixe de t qui est aussi prefixe de u (2) on cherche le plus grand suffixe de t qui est aussi suffixe de u, et qui ne chevauche pas le prefixe trouve en (1). (3) l'union du prefixe et du suffixe trouves en (1), (2) doit etre egale a t. int est_collage(int *t, int n, int *u, int m) { int i = 0, j = 0; while (i < n && t[i] == u[i]) // (1) i++; while (i + j < n && t[n - 1 - j] == u [m - 1 - j]) // (2) j++; return i + j == n; (3) } ---------- Exercice 2 ---------- Un exercice elementaire. On commence par faire l'inventaire des lettres de la premiere ligne. Pour chaque ligne supplementaire, on fait l'inventaire de ses lettres, et on le compare a celui de la premiere ligne. (1) on declare deux tableaux de 26 cases (une case par lettre), initialises a 0. (2) si le texte est vide, la condition est trivialement verifiee. (3) sinon, on fait l'inventaire des lettres de la toute premiere ligne dans le premier tableau. (4) pour chacune des autres lignes, on fait l'inventaire des lettres de cette ligne dans le second tableau. (5) on compare les deux inventaires, tout en renitialisant le second - ils doivent etre identiques. int est_ha(char *s) { int ref[25] = {}; // (1) int suc[25] = {}; int i = 0, j; if (s[i] == '\0') // (2) return 1; while (s[i] != '\n') { // (3) if (s[i] >= 'a' && s[i] <= 'z') ref[s[i] - 'a']++; i++; } i++; while (s[i] != '\0') { while (s[i] != '\n') { // (4) if (s[i] >= 'a' && s[i] <= 'z') ref[s[i] - 'a']++; i++; } for (j = 0; j < 25; j++) { // (5) if (ref[j] != suc[j]) return 0; suc[j] = 0; } i++; } return 1; } ---------- Exercice 3 ---------- L'exercice est base sur le meme principe que le precedent, mais il faut faire les inventaires des bords gauche et droit du texte - rien de tres difficile, mais il faut etre un peu methodique. Voici la solution la plus simple, mais pas la plus generale : on suppose qu'aucune ligne n'est vide, et que chaque ligne commence et se termine par une lettre. (1) on declare deux tableaux de 26 cases (une case par lettre), initialises a 0. on parcourt ensuite les lignes successivement. (2) en debut de ligne (donc, sur la premiere lettre, avec les hypotheses faites precedemment), on memorise la lettre courante. (3) on se deplace ensuite jusqu'a la fin de la ligne courante (donc sur la derniere lettre). (4) on memorise la lettre courante. (5) on passe le marqueur de fin de ligne. (6) en fin de parcours, on compare les deux inventaires : ils doivent etre identiques. int est_ada(char *s) { int g[25] = {}; // (1) int d[25] = {}; int i = 0; while (s[i] != '\0') { g[s[i] - 'a']++; // (2) while (s[i + 1] != '\n') // (3) i++; d[s[i] - 'a']++; // (4) i +=2; // (5) } for (i = 0; i < 25; i++) // (6) if (g[i] != d[i]) return 0; return 1; } Si l'on veut une solution plus complete, quelques precautions sont a prendre : il peut y avoir des separations avant la premiere lettre d'une ligne, ou apres sa derniere lettre. Il peut aussi y avoir des lignes ne comportant aucune lettre - dans ce cas, l'enonce ne dit pas clairement s'il faut les ignorer, ou si l'on doit considerer que la propriete n'est pas verifiee. La solution ci-dessous choisit de les ignorer. (1) on declare deux tableaux de 26 cases (une case par lettre), initialises a 0. on parcourt ensuite les lignes successivement. (2) on cherche la premiere lettre de la ligne courante. (3) on ignore les lignes ne contenant aucune lettre (variante possible : renvoyer 0). (4) sinon, on ajoute a l'inventaire la premiere lettre trouvee. (5) on se deplace ensuite jusqu'a la fin de la ligne courante, en memorisant la position de la derniere lettre trouvee. (6) on ajoute a l'inventaire la derniere lettre trouvee. (7) en fin de parcours, on compare les deux inventaires : ils doivent etre identiques. int est_ada(char *s) { int g[25] = {}; // (1) int d[25] = {}; int i = 0, j; while (s[i] != '\0') { while ((s[i] <= 'a' || s[i] >= 'z') && s[i] != '\n') // (2) i++; if (s[i] == '\n') { // (3) i++; continue; } g[s[i] - 'a']++; // (4) while (s[i] != '\n') { // (5) if (s[i] >= 'a' && s[j] <= 'n') j = i; i++; } d[s[j] - 'a']++; // (6) i++; } for (i = 0; i < 25; i++) // (7) if (g[i] != d[i]) return 0; return 1; } ---------- Exercice 4 ---------- Une exercice demandant un peu plus de travail, et qui a ete totalement incompris. Il faut deplacer en parallele deux indices : un se deplacant sur les premieres lettres de chaque ligne, l'autre se deplacant a rebours sur les dernieres lettres de chaque ligne - en comparant les caracteres aux deux positions, et jusqu'a ce que les indices se croisent. Comme precedemment, il peut y avoir des espaces avant la premiere lettre et apres la derniere lettre d'une ligne, ainsi que des lignes ne comportant aucune lettre - la solution ci-dessous choisit de les ignorer. (1) on place un indice (i) au debut du texte, un autre (j) a la fin. (2) i avance jusqu'a rencontrer la premiere lettre d'une ligne non vide (ou j). (3) j recule jusqu'a rencontrer la derniere lettre d'une ligne non vide (ou i). (4) les lettres en i et j doivent etre egales. (5) i avance jusqu'a la fin de sa ligne (ou jusqu'a j). (6) j recule jusqu'a la fin de la ligne precedente (ou jusqu'a i). int est_adp(char *s) { int i = 0, j = strlen(s); // (1) while(i < j) { while ((s[i] <= 'a' || s[i] >= 'z') && i < j) i++; // (2) while ((s[j] <= 'a' || s[j] >= 'z') && i < j) j--; // (3) if (s[i] != s[j]) // (4) return 0; while (s[i] != '\n' && i < j) i++; // (5) while (s[j] != '\n' && i < j) j--; // (6) } return 1; } --------------- Exercice 5 et 6 --------------- Deux exercices tres elementaires - et encore simplifies par le fait que les fonctions sont en void. Les reponses sont globalement tres confuses. ----- Ex. 5 ----- (1) et (2) la liste doit contenir au moins deux clefs. (3) si n > 0, la fusion se fait plus loin. (4) sinon, on fusionne les deux premieres clefs. void fusionner(struct cell *pc, int n) { struct cell *pcs; if (pc == NULL) // (1) return; if (pc -> suiv == NULL) // (2) return; if (n > 0) { // (3) fusion(pc -> suiv, n - 1); return; } pcs = pc -> suiv; // (4) pc -> clef += pcs -> clef; pc -> suiv = pcs -> suiv; free(pcs); } ----- Ex. 6 ----- (1) la liste doit contenir au moins une clef. (2) si n > 0, le deploiement se fait plus loin. (3) sinon, on deploie la premiere cellule. void deployer(struct cell *pc, int n) { struct cell *pcn; if (pc == NULL) // (1) return; if (n > 0) { // (2) deployer(pc -> suiv); return; } pc -> clef -= 1; // (3) pcn = malloc(sizeof(struct cell)); pcn -> clef = 1; pcn -> suiv = pc -> suiv; pc -> suiv = pcn; }