Add the two exams correction
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Sat, 15 Apr 2017 14:54:56 +0000 (16:54 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Sat, 15 Apr 2017 14:54:56 +0000 (16:54 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
exam1/ExamenAlgo1correction.c [new file with mode: 0644]
exam1/Makefile [new file with mode: 0644]
exam2/ExamenAlgo2correction.c [new file with mode: 0644]
exam2/Makefile [new file with mode: 0644]

diff --git a/exam1/ExamenAlgo1correction.c b/exam1/ExamenAlgo1correction.c
new file mode 100644 (file)
index 0000000..24f014e
--- /dev/null
@@ -0,0 +1,145 @@
+/******************************************************************************/
+/*              examen algo I : correction et implantation                    */
+/******************************************************************************/
+
+/*
+1)
+appel mystere(6 9 4 8 12 , 2)
+T[2]=4 T[3]=8
+T[2]=4 <= T[3]=8 donc retourner appel recursif avec k=3
+       appel mystere(6 9 4 8 12 , 3)
+       T[3]=8 T[4]=12
+       T[3]=8 <= T[4]=12 donc retourner appel recursif avec k=4
+               appel mystere(6 9 4 8 12 , 4)
+               k=4 et n-1=4 donc retourner VRAI
+reponse de mystere(6 9 4 8 12 , 2) = Vrai
+
+2)
+appel mystere(6 9 4 8 12 , 0)
+T[0]=6 T[1]=9
+T[0]=6 <= T[1]=9 donc retourner appel recursif avec k=1
+       appel mystere(6 9 4 8 12 , 1)
+       T[1]=9 T[2]=4
+       T[1]=9 > T[2]=4 donc retourner FAUX
+reponse de appel mystere(6 9 4 8 12 , 0) = Faux
+
+3)
+La fonction mystere(t, k) retourne Vrai si la suite d'entiers contenue dans
+le tableau t a partir de l'indice k est croissante et retourne Faux sinon.
+
+4)
+Le pire des cas correspond a l'appel mystere(t,k) pour un tableau croissant 
+a partir de l’indice k. Il y a dans ce cas n-k appels recursifs en comptant 
+l'appel initial.
+
+5) voir, plus bas, la fonction estDans(int *T, int x, int k, int n) implantant l'algorithme.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+void affichertab(int *T, int taille)
+{
+    int i;
+    for (i = 0; i < taille; i++) {
+       printf("%d ", T[i]);
+    }
+}
+
+
+int mystere(int *T, int k, int n, int coltab)
+{
+    int i = 0;
+    for (i = 0; i < coltab; i++)
+       printf("\t");
+    printf("appel mystere(");
+    affichertab(T, n);
+    printf(", %d)\n", k);
+
+    if (k == n - 1) {
+       for (i = 0; i < coltab; i++)
+           printf("\t");
+       printf("k=%d et n-1=%d donc retourner VRAI\n", k, n - 1);
+       return 1;
+    }
+
+    for (i = 0; i < coltab; i++)
+       printf("\t");
+    printf("T[%d]=%d T[%d]=%d\n", k, T[k], k + 1, T[k + 1]);
+
+    if (T[k] > T[k + 1]) {
+       for (i = 0; i < coltab; i++)
+           printf("\t");
+       printf("T[%d]=%d > T[%d]=%d donc retourner FAUX\n", k, T[k], k + 1,
+              T[k + 1]);
+       return 0;
+    }
+
+    for (i = 0; i < coltab; i++)
+       printf("\t");
+    printf
+       ("T[%d]=%d <= T[%d]=%d donc retourner appel recursif avec k=%d\n",
+        k, T[k], k + 1, T[k + 1], k + 1);
+    return mystere(T, k + 1, n, coltab + 1);
+}
+
+
+
+int estDans(int *T, int x, int k, int n)
+{
+    if (k > n - 1)
+       return 0;
+    if (T[k] == x)
+       return 1;
+    return estDans(T, x, k + 1, n);
+}
+
+
+/*****************************************************************/
+main()
+{
+    int T[] = { 6, 9, 4, 8, 12 };
+    int n = 5;
+
+    int reponse = mystere(T, 2, n, 0);
+    printf("reponse = %d\n", reponse);
+
+    printf("\n");
+
+    reponse = mystere(T, 0, n, 0);
+    printf("reponse = %d\n", reponse);
+
+    printf("\n");
+    printf("estDans(T,9,0) = %d\n", estDans(T, 9, 0, n));
+    printf("estDans(T,9,2) = %d\n", estDans(T, 9, 2, n));
+    printf("estDans(T,12,3) = %d\n", estDans(T, 12, 3, n));
+    printf("estDans(T,12,5) = %d\n", estDans(T, 12, 5, n));
+}
+
+
+/** trace d'execution *********************************
+appel mystere(6 9 4 8 12 , 2)
+T[2]=4 T[3]=8
+T[2]=4 <= T[3]=8 donc retourner appel recursif avec k=3
+       appel mystere(6 9 4 8 12 , 3)
+       T[3]=8 T[4]=12
+       T[3]=8 <= T[4]=12 donc retourner appel recursif avec k=4
+               appel mystere(6 9 4 8 12 , 4)
+               k=4 et n-1=4 donc retourner VRAI
+reponse = 1
+
+appel mystere(6 9 4 8 12 , 0)
+T[0]=6 T[1]=9
+T[0]=6 <= T[1]=9 donc retourner appel recursif avec k=1
+       appel mystere(6 9 4 8 12 , 1)
+       T[1]=9 T[2]=4
+       T[1]=9 > T[2]=4 donc retourner FAUX
+reponse = 0
+
+estDans(T,9,0) = 1
+estDans(T,9,2) = 0
+estDans(T,12,3) = 1
+estDans(T,12,5) = 0
+*********************************************************/
diff --git a/exam1/Makefile b/exam1/Makefile
new file mode 100644 (file)
index 0000000..4159a43
--- /dev/null
@@ -0,0 +1,79 @@
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exam1
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME)
+
+CC=gcc
+LD=gcc
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+CFLAGS := $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(BINARY_NAME): $(OBJS)
+       @echo "[LD ] $@"
+       @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+       @echo "[C  ] $*"
+       @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+       @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+clean:
+       @echo "[CLN]"
+       -@rm -r $(BUILDDIR)
+       -@rm $(BINARY_NAME)
+
+disassemble: $(BINARY_NAME)
+       objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+       objdump -t $< | sort | less
diff --git a/exam2/ExamenAlgo2correction.c b/exam2/ExamenAlgo2correction.c
new file mode 100644 (file)
index 0000000..1ab1558
--- /dev/null
@@ -0,0 +1,290 @@
+/******************************************************************************/
+/*                     examen algo II avec implantation                       */
+/*                       des expressions arithmetiques                        */
+/******************************************************************************/
+
+
+/* Exercice 1 : questions de cours (correction rapide)
+
+1) Utilisation d'une fonction de hachage sur une valeur pour calculer la cle qui est alors utilisee pour ranger la valeur dans un tableau a l'indice cle.
+La recherche d'une valeur est alors immediate : calcul de la cle puis acces a l'element d'indice cle dans le tableau.
+
+2) Dans le pire des cas, AVL car O(log n) pour recherche, insertion et suppression. 
+Et aussi, tableau (trie) avec methode dichotomique, mais O(log n) pour la recherche seulement.
+
+3) En moyenne, Hachage car O(1) pour recherche, insertion et suppression.
+
+4) Dans une feuille. 
+Par l'absurde, si l'element de plus petite priorite n'est pas dans une feuille alors cela signifie qu'il existe un noeud fils de plus grande priorite. Contradiction avec la definition d'un tas (tout noeud est >= a chacun de ses fils).
+*/
+
+
+/* Exercice 2 : expressions arithmetiques*/
+
+/* remarques : pour l'examen, algorithmes en pseudo-code, 
+avec des libertes possibles comme dire "la valeur est un operateur". 
+Bien entendu, il y a plusieurs facon de rediger un algo. 
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef char element;
+
+typedef struct noeud {
+    element valeur;
+    struct noeud *gauche;
+    struct noeud *droit;
+} NOEUD, *EA;
+
+
+/* Creation d'un arbre vide */
+NOEUD *arbre_vide()
+{
+    return NULL;
+}
+
+
+/* Affichage du contenu de l'arbre (parcours infixe) */
+void affiche(NOEUD * p)
+{
+    if (p) {
+       if (p->gauche != NULL)
+           printf("( ");       /* p est une feuille (si gauche null alors droit aussi) */
+       affiche(p->gauche);
+       printf("%c ", p->valeur);
+       affiche(p->droit);
+       if (p->droit != NULL)
+           printf(") ");       /* p est une feuille (si droit null alors gauche aussi) */
+    }
+}
+
+
+/* Test si un arbre est bien une EA valide */
+int est_valide(NOEUD * p)
+{
+    if (p == NULL)
+       return 1;
+    else if (p->valeur == '+' || p->valeur == '-' || p->valeur == '*'
+            || p->valeur == '/')
+       return (est_valide(p->gauche) && est_valide(p->droit));
+    else
+       return (p->gauche == NULL && p->droit == NULL);
+}
+
+
+/* Test si deux arbres sont egaux (identiques) */
+int egal(NOEUD * A1, NOEUD * A2)
+{
+    if (A1 == NULL || A2 == NULL)
+       return (A1 == NULL && A2 == NULL);
+    else
+       return ((A1->valeur == A2->valeur)
+               && egal(A1->gauche, A2->gauche)
+               && egal(A1->droit, A2->droit));
+}
+
+
+/* Evaluation d'une EA (un arbre) */
+int eval(NOEUD * p)
+{
+    if (p->valeur == '+')
+       return eval(p->gauche) + eval(p->droit);
+    else if (p->valeur == '-')
+       return eval(p->gauche) - eval(p->droit);
+    else if (p->valeur == '*')
+       return eval(p->gauche) * eval(p->droit);
+    else if (p->valeur == '/')
+       return eval(p->gauche) / eval(p->droit);
+    else
+       return atoi(&p->valeur);        /* convertion du char en int */
+}
+
+
+/* Construction de l'arbre correspondant a une EA lue au clavier */
+NOEUD *construit(char courant)
+{
+    NOEUD *p = NULL;
+
+    /* printf("traitement de %c\n",courant); */
+
+    if (courant != '(' && courant != ')' && courant != '+'
+       && courant != '-' && courant != '*' && courant != '/') {
+       p = (NOEUD *) malloc(sizeof(NOEUD));
+       p->valeur = courant;
+       p->gauche = NULL;
+       p->droit = NULL;
+    } else {                   /* courant est '(' */
+       /* l'EA est de la forme (E1 operateur E2) */
+
+       /* lecture de E1 */
+       char courant2;
+       scanf("%c", &courant2);
+       getchar();
+       p = (NOEUD *) malloc(sizeof(NOEUD));
+       /* traitement de E1 */
+       p->gauche = construit(courant2);
+
+       /* lecture de l'operateur */
+       char courant3;
+       scanf("%c", &courant3);
+       getchar();
+       p->valeur = courant3;
+
+       /* lecture de E2 */
+       char courant4;
+       scanf("%c", &courant4);
+       getchar();
+       /* traitement de E2 */
+       p->droit = construit(courant4);
+
+       /* lecture de ')' */
+       char courant5;
+       scanf("%c", &courant5);
+       getchar();
+    }
+
+    return p;
+}
+
+
+
+
+/* Affichage de l'arbre (sous forme arborescente) */
+void affiche_arbre(NOEUD * p, int col)
+{
+    int i;
+    if (p) {
+       affiche_arbre(p->droit, col + 1);
+       for (i = 0; i < col; i++)
+           printf("   ");
+       printf("%c\n", p->valeur);
+       affiche_arbre(p->gauche, col + 1);
+    }
+}
+
+
+/* Destruction de l'arbre de racine p en recuperant la place occupee (free) par chacun des noeuds  */
+NOEUD *detruis_arbre(NOEUD * p)
+{
+    if (p == NULL)
+       return p;
+    else {
+       p->gauche = detruis_arbre(p->gauche);
+       p->droit = detruis_arbre(p->droit);
+       free(p);
+       p = NULL;
+       return p;
+    }
+}
+
+
+/* Creation d'un noeud */
+NOEUD *cree_noeud(char valeur, NOEUD * filsgauche, NOEUD * filsdroit)
+{
+    NOEUD *p = (NOEUD *) malloc(sizeof(NOEUD));
+    p->valeur = valeur;
+    p->gauche = filsgauche;
+    p->droit = filsdroit;
+    return p;
+}
+
+
+/****************************************************************************/
+main()
+{
+    NOEUD *ea = arbre_vide();
+
+    /* creation "a la main" de (9 + (3 * 2)) */
+    NOEUD *feuille9 = cree_noeud('9', NULL, NULL);
+    NOEUD *feuille3 = cree_noeud('3', NULL, NULL);
+    NOEUD *feuille2 = cree_noeud('2', NULL, NULL);
+    NOEUD *ea2 = cree_noeud('*', feuille3, feuille2);
+    ea = cree_noeud('+', feuille9, ea2);
+
+    printf("expression arithmetique : \n");
+    affiche(ea);
+    printf("\n");
+    affiche_arbre(ea, 0);
+
+    int valide = est_valide(ea);
+    if (valide == 1)
+       printf("l'expression est valide\n");
+    else
+       printf("l'expression n'est pas valide\n");
+
+    int resultat = eval(ea);
+    printf("resultat = %d\n", resultat);
+
+
+    /* test egalite */
+    NOEUD *eab = arbre_vide();
+    NOEUD *feuille9b = cree_noeud('9', NULL, NULL);
+    NOEUD *feuille3b = cree_noeud('3', NULL, NULL);
+    NOEUD *feuille2b = cree_noeud('2', NULL, NULL);
+    NOEUD *ea2b = cree_noeud('*', feuille3b, feuille2b);
+    eab = cree_noeud('+', feuille9b, ea2b);
+    printf("\nexpression arithmetique 2 : \n");
+    affiche(eab);
+    printf("\n");
+
+    int egalite = egal(ea, eab);
+    if (egalite == 1)
+       printf("les 2 expressions sont identiques\n");
+    else
+       printf("les 2 expressions ne sont pas identiques\n");
+
+
+    /* test construction */
+    printf
+       ("\nsaisir une expression arithmetique (un caractere a la fois) : \n");
+    char courant;
+    scanf("%c", &courant);
+    getchar();                 /* lecture de '(' */
+    ea = construit(courant);
+
+    printf("expression arithmetique : \n");
+    affiche(ea);
+    printf("\n");
+    affiche_arbre(ea, 0);
+    printf("resultat = %d\n", eval(ea));
+}
+
+/***** exemple d'execution ********************************************
+expression arithmetique : 
+( 9 + ( 3 * 2 ) ) 
+      2
+   *
+      3
++
+   9
+l'expression est valide
+resultat = 15
+
+expression arithmetique 2 : 
+( 9 + ( 3 * 2 ) ) 
+les 2 expressions sont identiques
+
+saisir une expression arithmetique (un caractere a la fois) : 
+(
+9
++
+(
+3
+*
+2
+)
+)
+expression arithmetique : 
+( 9 + ( 3 * 2 ) ) 
+      2
+   *
+      3
++
+   9
+resultat = 15
+*******************************************************************/
diff --git a/exam2/Makefile b/exam2/Makefile
new file mode 100644 (file)
index 0000000..d744a01
--- /dev/null
@@ -0,0 +1,79 @@
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exam2
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME)
+
+CC=gcc
+LD=gcc
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+CFLAGS := $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(BINARY_NAME): $(OBJS)
+       @echo "[LD ] $@"
+       @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+       @echo "[C  ] $*"
+       @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+       @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+clean:
+       @echo "[CLN]"
+       -@rm -r $(BUILDDIR)
+       -@rm $(BINARY_NAME)
+
+disassemble: $(BINARY_NAME)
+       objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+       objdump -t $< | sort | less