0% ont trouvé ce document utile (0 vote)
40 vues10 pages

Correction Kholle6

Exercice corrigé MP2I Kholle

Transféré par

Ghislain PANDRY
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
40 vues10 pages

Correction Kholle6

Exercice corrigé MP2I Kholle

Transféré par

Ghislain PANDRY
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Coadage par Plage - Correction

Samy Jaziri

1 Compression des séquences identiques


Structure de pile
La structure de donnée est dénie comme ceci :

typedef unsigned int uint;

typedef struct maillon {


char caractere;
uint repetition;
struct maillon* suivant;
} maillon;

typedef struct pile {


maillon* sommet;
uint taille;
uint nb_maillon;
} pile;

On conserve un champ taille et un champ nb_maillon pour accéder à la taille de la pile et au


nombre d'éléments en O(1). Ces champs seront mis à jour dans les fonctions empiler et depiler
en temps constant.

// Initialisation de pile
pile* creer_pile_vide() {
pile* p = (pile*) malloc(sizeof(pile));
p->sommet = NULL;
p->taille = 0;
p->nb_maillon = 0;
return p;
}

1
Khôlle Informatique MP2I Janson de Sailly

// Déstruction de la pile
void detruire_pile(pile* p) {
maillon* n;
while (p->sommet) {
n = p->sommet->suivant;
free(p->sommet);
p->sommet = n;
}
free(p);
}

void empiler(pile* p, char c) {


maillon* m;
if(p->sommet && p->sommet->caractere == c)
++p->sommet->repetition;
else {
m = (maillon*) malloc(sizeof(maillon));
m->caractere = c;
m->repetition = 0;
m->suivant = p->sommet;
p->sommet = m;
++p->nb_maillon;
}
++p->taille;
}

// Prérequis : la pile est non vide


char depiler(pile* p) {
char c = p->sommet->caractere;
maillon* n;
if(p->sommet->repetition == 0) {
n = p->sommet->suivant;
free(p->sommet);
p->sommet = n;
--p->nb_maillon;
} else
--p->sommet->repetition;
--p->taille;
return c;
}

2022 2 [email protected]
Khôlle Informatique MP2I Janson de Sailly

Codage
Le codage consiste simplement à empiler les caractères un par un.

pile* codage_chaine(char* s) {
pile* encodeur = creer_pile_vide();
for(;*s;++s)
empiler(encodeur,*s);
return encodeur;
}

empiler tourne en temps constant donc codage_chaine est en O(n) avec n la longueur de la chaîne
à encoder.
Le décodage consiste à dépiler les éléments un per un.

char* decodage_chaine(pile *p) {


char* s_decodee = (char*) malloc(sizeof(char) * p->taille + 1);
char* tmp = s_decodee+p->taille;
*tmp = '\0';
while(p->sommet)
*(--tmp) = depiler(p);
return s_decodee;
}

depiler tourne en temps constant donc decodage_chaine est en O(n) avec n la taille de la pile.
La taille de la pile est exactement la longueur de la chaîne encodée.
La pile représentant une chaîne n'occupe pas nécessairement moins d'espace que la chaîne. En eet,
si la chaîne n'a pas de séquence de caractère identique, la pile contiendra autant d'élément que la
chaîne. Or un élément de la pile occupe
sizeof (uint) + sizeof (char) + sizeof (maillon∗) = 4 + 1 + 8 = 13 octets

Alors qu'un caractère occupe 1 octet.


Il faut donc, pour que ce codage soit intéressant, que la chaîne soit majoritairement composée de
longue séquence de caractère. Il devient intéressant de remplacer une séquence par son codage
lorsqu'elle dépasse 13 caractères. Il faut par ailleurs que le gain réaliser sur chaque longue séquence,
compense la perte réalisée sur les courtes séquences (moins de 13 caractères).

Liste aléatoire
On déni une fonction générant Sn .

2022 3 [email protected]
Khôlle Informatique MP2I Janson de Sailly

char* s(uint u0, uint n) {


uint u = u0;
char* s = (char*) malloc(sizeof(char) * (n + 2));
s[n+1] = '\0';
for(uint i = 0; i <= n; i++) {
s[i] = u % 144 == 0 ? 'N' : 'B';
u = ( u * 15091 ) % 64007;
}
return s;
}

2 Codage par nombre optimal de carrés blancs


Type Image
typedef struct image {
char** pixels;
uint largeur;
uint hauteur;
} image;

image* creer_image_noire(uint largeur, uint hauteur) {


image* img = (image*) malloc(sizeof(image));
img->largeur = largeur;
img->hauteur = hauteur;
img->pixels = (char**) malloc(sizeof(char*) * largeur);
for(uint i = 0 ; i < img->largeur ; ++i) {
img->pixels[i] = (char*) malloc(sizeof(char) * img->hauteur);
for(uint j = 0 ; j < img->hauteur ; ++j)
img->pixels[i][j] = 'N';
}
return img;
}

void detruire_image(image* img) {


for(uint i = 0 ; i < img->largeur ; ++i)
free(img->pixels[i]);
free(img->pixels);
free(img);
}

2022 4 [email protected]
Khôlle Informatique MP2I Janson de Sailly

Plus grand carré blanc


Notons PGCB(x,y) le plus grand carré blanc dont le coin inférieur droit est le pixel (x, y).
Pour résoudre le sous-problème (?) associé au pixel (x, y) on remarque qu'un carré blanc dont le
coin inférieur droit est (x, y) de taille n est égal à l'union des carrés blancs de taille n − 1 dont les
coins inférieurs droit sont (x − 1, y), (x, y − 1)et(x − 1, y − 1) et de (x, y) lui-même.
On montre que PGCB(x,y) = 1 + min(PGCB(x-1,y), PGCB(x,y-1), PGCB(x-1,y-1)).
Soit n la taille de PGCB(x,y). On peut en conclure que les trois carrés de taille n − 1 dont les coins
inférieur droit sont (x − 1, y), (x, y − 1)et(x − 1, y − 1) sont blancs et inclus dans PGCM(x,y). Au
moins l'un de ces carrés est maximal, sinon les pixels (x − n, y), (x − n, y − 1), . . . , (x − n, y − n)
appartiendrait à PGCB(x-1,y) et les pixels (x, y − n), (x − 1, y − n), . . . , (x − n, y − n) appartiendrait
à PGCB(x,y-1). Ces pixels serait donc blanc et on pourrait étendre PGCB(x,y) pour qu'il forme
un carré blanc de taille n + 1 dont le coin inférieur est (x, y). Ce contredirait la maximalité de
PGCB(x,y).
A l'inverse, si on prend n = 1 + min(PGCB(x-1,y), PGCB(x,y-1), PGCB(x-1,y-1)) on note déjà
que le carré de taille n et aillant comme coin inférieur droit le pixel (x, y) est un carré blanc. Si il
n'était pas maximal, le carré de taille n + 1 et aillant comme coin inférieur droit le pixel (x, y) serait
un carré blanc. Les trois carrés de taille n dont les coins inférieur droit sont (x−1, y), (x, y −1)et(x−
1, y − 1) serait blancs ce qui contredirait l'hypothèse de maximalité d'un des carrés PGCB(x-1,y),
PGCB(x,y-1), ou PGCB(x-1,y-1).

uint min3( uint a, uint b, uint c ) {


if(a < b && a < c)
return a;
if(b < c)
return b;
return c;
}

2022 5 [email protected]
Khôlle Informatique MP2I Janson de Sailly

uint plus_grand_carre_blanc(image* img) {


uint max = 0;
uint** matrice = (uint**) malloc(sizeof(uint*) * img->largeur);
for(uint i = 0 ; i < img->largeur ; ++i) {
matrice[i] = (uint*) malloc(sizeof(uint) * img->hauteur);
for(uint j = 0 ; j < img->hauteur ; ++j)
if(img->pixels[i][j] == 'B') {
matrice[i][j] = 1;
if(i > 0 && j > 0)
matrice[i][j] += min3(matrice[i-1][j],
matrice[i][j-1],
matrice[i-1][j-1]);
if(matrice[i][j] > max)
max = matrice[i][j];
} else {
matrice[i][j] = 0;
}
}
for(uint i = 0 ; i < img->largeur ; ++i)
free(matrice[i]);
free(matrice);
return max;
}

L'algorithme utilise un tableau de dimension l × h et produit une image de dimensions l × h, la


complexité est donc en O(l h).

Image noir et blanc aléatoires


On dénit une fonction i qui renvoie l'image associée à la chaîne Sn :

image* i(char* s, uint t) {


image* img = creer_image_noire(t,t);
for(uint i = 0 ; i < img->largeur ; ++i)
for(uint j = 0 ; j < img->largeur ; ++j)
img->pixels[i][j] = s[i * 212 + j];
return img;
}

Codage
Lors du calcul de PGCB(x,y) on décide de garder PGCB(x,y) et d'éliminer parmi PGCB(x-1,y),
PGCB(x,y-1), et PGCB(x-1,y-1)) les carrés entièrement inclus dans PGCB(x,y) et de garder les
autres. On ne peut pas obtenir un plus petit nombre de carrés couvrant sans modier les carrés
déjà calculer et donc s'éloigner d'une heuristique gloutonne. On conservera la liste des carrés à

2022 6 [email protected]
Khôlle Informatique MP2I Janson de Sailly

conserver dans une matrice de booléen représentant pour chaque pixel, est-ce que PGCB(x,y) sera
conservé dans le codage nal ou non.

uint* codage_image(image* img) {


uint taille_code = 0;
uint *code, *code_tmp;
bool** coins = (bool**) malloc(sizeof(bool*) * img->largeur);
uint** matrice = (uint**) malloc(sizeof(uint*) * img->largeur);
for(uint i = 0 ; i < img->largeur ; ++i) {
coins[i] = (bool*) malloc(sizeof(bool) * img->hauteur);
matrice[i] = (uint*) malloc(sizeof(uint) * img->hauteur);
for(uint j = 0 ; j < img->hauteur ; ++j) {
if(img->pixels[i][j] == 'B') {
matrice[i][j] = 1;
coins[i][j] = true;
++taille_code;
if(i > 0 && j > 0) {
matrice[i][j] += min3(matrice[i-1][j],
matrice[i][j-1],
matrice[i-1][j-1]);
if(coins[i-1][j] && matrice[i][j] > matrice[i-1][j]) {
coins[i-1][j] = false;
--taille_code;
}
if(coins[i][j-1] && matrice[i][j] > matrice[i][j-1]) {
coins[i][j-1] = false;
--taille_code;
}
if(coins[i-1][j-1] && matrice[i][j] > matrice[i-1][j-1]) {
coins[i-1][j-1] = false;
--taille_code;
}
}
} else {
matrice[i][j] = 0;
coins[i][j] = false;
}
}
}

2022 7 [email protected]
Khôlle Informatique MP2I Janson de Sailly

code = (uint*) malloc(sizeof(uint) * ( taille_code * 3 + 3) );


code_tmp = code;
*code_tmp = taille_code;
*(++code_tmp) = img->largeur;
*(++code_tmp) = img->hauteur;
for(uint i = 0 ; i < img->largeur ; ++i) {
for(uint j = 0 ; j < img->hauteur ; ++j) {
if(coins[i][j]) {
*(++code_tmp) = i;
*(++code_tmp) = j;
*(++code_tmp) = matrice[i][j];
}
}
}
for(uint i = 0 ; i < img->largeur ; ++i) {
free(matrice[i]);
free(coins[i]);
}
free(matrice);
free(coins);
return code;
}

L'algorithme tourne en O(n2 ) et utilise deux tableaux de dimension n2 en plus de renvoyer une
image de dimension n × n. La complexité spatiale est donc O(n2 ).

image* decodage_image(uint* code) {


uint taille_code = code[0];
uint largeur = code[1];
uint hauteur = code[2];
uint x, y, c;
image* img = creer_image_noire(largeur,hauteur);
for(uint k = 3 ; k <= taille_code * 3 ; k += 3) {
x = code[k];
y = code[k+1];
c = code[k+2];
for(uint i = 0; i < c ; ++i)
for(uint j = 0; j < c ; ++j)
img->pixels[x-i][y-j] = 'B';
}
return img;
}

2022 8 [email protected]
Khôlle Informatique MP2I Janson de Sailly

3 Achage des résultats de la che réponse

#include <stdio.h>
#include <stdlib.h>
#include "codage_par_plage.h"

int main( int argc, char** argv ) {


if (argc != 2) {
fprintf(stderr, "Usage : %s u0\n", argv[0]);
exit(EXIT_FAILURE);
}
int u0 = atoi(argv[1]);
char* s1000 = s(u0, 1000);
char* s100000 = s(u0, 100000);
char* s12000 = s(u0, 12000);
pile* code_s1000 = codage_chaine(s1000);
pile* code_s12000 = codage_chaine(s12000);
pile* code_s100000 = codage_chaine(s100000);
printf("Question 4 : a) %i b) %i c) %i\n",
code_s1000->nb_maillon,
code_s12000->nb_maillon,
code_s100000->nb_maillon);

char* s212x212 = s(u0, 212*212);


char* s512x512 = s(u0, 512*512);
char* s1000x1000 = s(u0, 1000*1000);
image* img212x212 = i(s212x212,212);
image* img512x512 = i(s512x512,512);
image* img1000x1000 = i(s1000x1000,1000);
printf("Question 8 : a) %i b) %i c) %i\n",
plus_grand_carre_blanc(img212x212),
plus_grand_carre_blanc(img512x512),
plus_grand_carre_blanc(img1000x1000));
uint* code212x212 = codage_image(img212x212);
uint* code512x512 = codage_image(img512x512);
uint* code1000x1000 = codage_image(img1000x1000);
printf("Question 11 : a) %ld%% b) %ld%% c) %ld\%%\n",
100 - ((code212x212[0]*3+3) * sizeof(uint) * 100)
/ (212*212*sizeof(char)) ,
100 - ((code512x512[0]*3+3) * sizeof(uint) * 100)
/ (512*512*sizeof(char)) ,
100 - ((code1000x1000[0]*3+3) * sizeof(uint) * 100)
/ (1000*1000*sizeof(char)) );

2022 9 [email protected]
Khôlle Informatique MP2I Janson de Sailly

free(s1000);
free(s100000);
free(s12000);
detruire_pile(code_s1000);
detruire_pile(code_s12000);
detruire_pile(code_s100000);
free(s212x212);
free(s512x512);
free(s1000x1000);
detruire_image(img212x212);
detruire_image(img512x512);
detruire_image(img1000x1000);
free(code212x212);
free(code512x512);
free(code1000x1000);

return EXIT_SUCCESS;
}

2022 10 [email protected]

Vous aimerez peut-être aussi