ajout travail control machine kara-mosr

This commit is contained in:
2025-10-15 17:04:33 +02:00
commit 966fde99f3
4 changed files with 284 additions and 0 deletions

193
EX1.c Normal file
View File

@@ -0,0 +1,193 @@
/*Je me suis pas super bien organise le fichierest long pour rien le main est trop long
Je me suis lancer dans l'utilisation d'allocation et de pointeur ce qui etat peut etre pas necessaire
j'ai essayer de commenter et de bien expliquer dans reponses.txt pour que ca reste comprehensible
Et puis dans le main j'ai mis pas mal de printf qui devrait aider la comprehension a l'execution
Pour compiler :
gcc -pg -o ex1 EX1.c
./ex1
gprof ./ex1
Riad Kara-Mostefa
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
int racineCarree(int n) {
if (n < 0) return -1;
if (n == 0 || n == 1) return n;
int i = 1;
while (i <= n / i) {
if ((n % i == 0) && (i == n / i)) {
return i;
}
i++;
}
return -1;
}
void racineCarreeTab(const int *in, int *out, size_t size) {
for (size_t i = 0; i < size; ++i) {
out[i] = racineCarree(in[i]);
}
}
static void affichageTab(const char *label, const int *t, size_t n) {
printf("%s[", label);
for (size_t i = 0; i < n; ++i) {
if (i) printf(",");
printf("%d", t[i]);
}
printf("]\n");
}
static void affichageTabLL(const char *label, const long long *t, size_t n) {
printf("%s[", label);
for (size_t i = 0; i < n; ++i) {
if (i) printf(",");
printf("%lld", t[i]);
}
printf("]\n");
}
void TriSpecial(const int *in, size_t n, long long *out) {
if (!in || !out || n == 0) return;
/*some original et some des racines*/
long long SommeOrigine = 0;
long long SommeSqrt = 0;
size_t nbNonEntieres = 0;
/* tab avec les racines carees*/
int *roots = (int*)malloc(n * sizeof(int));
if (!roots) {
for (size_t i = 0; i < n; ++i) {
int r = racineCarree(in[i]);
SommeOrigine += (long long)in[i];
SommeSqrt += (long long)r;
if (r == -1) ++nbNonEntieres;
}
roots = NULL;
} else {
for (size_t i = 0; i < n; ++i) {
int r = racineCarree(in[i]);
roots[i] = r;
SommeOrigine += (long long)in[i];
SommeSqrt += (long long)r;
if (r == -1) ++nbNonEntieres;
}
}
const int pair = ((nbNonEntieres % 2) == 0);
if (pair) {
for (size_t i = 0; i < n; ++i) {
if ((i % 2) == 0) out[i] = (long long)in[i];
else out[i] = SommeOrigine * (long long)in[i];
}
} else {
for (size_t i = 0; i < n; ++i) {
if ((i % 2) == 0) {
int r = roots ? roots[i] : racineCarree(in[i]);
out[i] = (long long)r;
} else {
out[i] = SommeSqrt * (long long)in[i];
}
}
}
free(roots);
}
int main(void) {
printf("EX1 : tests simples\n");
printf("racineCarree(9) = %d\n", racineCarree(9));
printf("racineCarree(10) = %d\n", racineCarree(10));
int t1[] = {9,25,4};
int r1[3];
racineCarreeTab(t1, r1, 3);
affichageTab("racineCarreeTab([9,25,4]) = ", r1, 3);
int t2[] = {10,36,2};
int r2[3];
racineCarreeTab(t2, r2, 3);
affichageTab("racineCarreeTab([10,36,2]) = ", r2, 3);
/* le gros tableau de test comme demande dans l'exo2 */
printf("\nEX2 : gros tableau (racineCarreeTab) \n");
const size_t N = 10000;
int *big = (int*)malloc(sizeof(int) * N);
int *res = (int*)malloc(sizeof(int) * N);
/*je verifie l'allocation memeoire*/
if (!big || !res) {
fprintf(stderr, "Allocation echouee pour EX2\n");
free(big); free(res);
return 1;
}
/* J'ai essaye de genere des carre parfait et des non-carres on va dire pour tester */
for (size_t i = 0; i < N; ++i) {
int base = 1000000 + (int)(i * 1237);
if (i % 997 == 0) {
int s = 2000 + (int)(i % 500);
base = s * s;
}
big[i] = base;
}
racineCarreeTab(big, res, N);
printf("res (debut 10) = [");
for (size_t i = 0; i < 10 && i < N; ++i) {
if (i) printf(",");
printf("%d", res[i]);
}
if (N > 10) printf(", ...]");
printf("\n");
printf("\n EX3 : tests TriSpecial\n");
{
int a1[] = {3,5,25,16};
long long out1[4];
TriSpecial(a1, 4, out1);
affichageTabLL("TriSpecial([3,5,25,16]) = ", out1, 4);
}
{
int a2[] = {36,9,100,2,3,7};
long long out2[6];
TriSpecial(a2, 6, out2);
affichageTabLL("TriSpecial([36,9,100,2,3,7]) = ", out2, 6);
}
/* On utilise un gros tableau comme demandéé dans l'exo4 */
printf("\nEX4 : gros tableau (TriSpecial)\n");
/*la sortie pour le long tableau de gros elements*/
long long *sortieLL = (long long*)malloc(sizeof(long long) * N);
if (!sortieLL) {
fprintf(stderr, "Allocation echouee pour EX4 (sortieLL)\n");
free(big); free(res);
return 1;
}
TriSpecial(big, N, sortieLL);
/*Je me suis dit que 10 elements suffisait pour voir si on a le resultat attendu donc j'en affiche que 10*/
printf("TriSpecial(big) (debut 10) = [");
for (size_t i = 0; i < 10 && i < N; ++i) {
if (i) printf(",");
printf("%lld", sortieLL[i]);
}
if (N > 10) printf(", ...]");
printf("\n");
/* Nettoyage */
free(sortieLL);
free(big);
free(res);
return 0;
}

BIN
ex1 Executable file

Binary file not shown.

BIN
gmon.out Normal file

Binary file not shown.

91
reponses.txt Normal file
View File

@@ -0,0 +1,91 @@
----------------------------------------EX2---------------------------------------
1-
racineCarree : Temps : 0.09s et on a 10 008 appels. Ca fait donc un temps moyen d'appel de 0.01ms
racineCarreeTab : avec grpof on nous dit que son temps d'execution est de 0s. On a 3 appels qui correspondent aux deux petits tableaux de test que j'ai dans mon main et au tableau
avec 10 000 elements tous plus grand que 1 000 000. Si son temps d'execution est aussi cours c'est parce qu'on appelle racineCarree. Si on prend cela en compte on voit que
racineCarreeTab s'execute sur 30s environ.
On a donc racineCarreeTab qui appel 10 006 fois racineCarree et les 2 autres sont dans le main avec les deux petits test que j'ai mis.
Pour resume on a racineCarreeTab qui ne consomme presque rien car tout est delegue a racineCareeTab qui est appele en boucle pour parcourir le tableau.
2-
Complexite cyclomatioque :
de racineCarree est de 5 car :
1 "if (n < 0)"
2 "if (n == 0 || n == 1) "
3 "while (i <= n / i)"
4 "if ((n % i == 0) && (i == n / i))"
de racineCareeTab est de 2 car on a que la boucle for :
La boucle "for (k = 0; k < size; ++k)"
Complexite Algorithmique :
---------de racineCarree : O(√n)-------------
Si n nest pas un carré parfait : on ne retourne pas avant la fin. Donc la boucle fait exactement ⌊√n⌋ itérations, puis on sort et on renvoie -1
Si n est un carré parfait : on retourne à i = √n donc la boucle fait √n itérations (la dernière est celle qui trouve la racine)
Dans tous les cas, le nombre ditérations est proportionnel à √n
-------- de racineCarreeTab dépend ----------
du nombre déléments dans le tableau qu'on note m
du temps dexécution de racineCarree() pour chaque élément
Et Puisque racineCarreeTab appelle racineCarree() m fois (une fois par élément du tableau) le coût total est la somme des coûts de chaque appel :
On va regarder le pire, c'est celui ou tous les elements du tableau sont proche de l'element le plus grand. Par exemple dans notre exemple avec des valeurs > 1 000 000.
On peut dire que toutes les valeurs sont proches de la plus grandes car a cette echelle de grandeur la difference est minim. On peut donc dire que dans le pire des cas
la complexite est dependante du max (la plus grande valeurs) et du nombre d'appels a la fonction racineCarree
on a comme complexite : O(m * √max)
----------------------------EX4--------------------------------
La complexite cyclomatique de TriSpecial :
1 : if (!in || !out || n == 0)
2 : if (!roots)
3 : for (...) (branche !roots)
4 : if (r == -1) (branche !roots)
5 : for (...) (branche else)
6 : if (r == -1) (branche else)
7 : if (pair)
8 : for (...) (branche pair)
9 : if (i % 2 == 0) (branche pair)
10 : for (...) (branche impair)
11 : if (i % 2 == 0) (branche impair)
Donc on a une complexite de 12 pour TriSpecial
La complexite cyclomatique de TriSpecial :
C'est le meme principe que racineCarreeTab et ca depend du nombre d'appel et de l'element le plus grand
On a O(N * √M) ou est M est le plus grand nombre et N le nombre d'appel.