• Aucun résultat trouvé

Ex.1 Autour de la fonctionnelle map - OCaml (25 minutes)

N/A
N/A
Protected

Academic year: 2022

Partager "Ex.1 Autour de la fonctionnelle map - OCaml (25 minutes)"

Copied!
7
0
0

Texte intégral

(1)

Cette dixième colle vous fera écrire une fonction simple en OCaml sur des listes, et un exercice en C sur des calculs sur des caractères ASCII.

Ex.1 Autour de la fonctionnelle map - OCaml (25 minutes)

1. Écrire la fonctionnellemap : ('a -> 'b) -> 'a list -> 'b list qui à une fonctionf : 'a -> 'b et à une liste [x0; x1; x2; ...; xn] de type 'a list associe la liste [f (x0); f (x1); f (x2); ...; f (xn)] de type 'b list.

# let rec map f liste = match liste with

| [] -> []

| head :: tail -> (f head) :: (map f tail)

;;val map : (’a -> ’b) -> ’a list -> ’b list = <fun>

# map (fun x -> 2*x) [1; 2; 3; 4];;

- : int list = [2; 4; 6; 8]

# map (fun x -> x+2021) [1; 2; 3; 4];;

- : int list = [2022; 2023; 2024; 2025]

2. Démontrer très soigneusement et rigoureusement la terminaison et la correction de votre fonction. S’il est nécessaire de faire des hypothèses, explicitez-les clairement.

Preuve de la terminaison :

Nous ferons l’hypothèse évidente que𝑓p𝑥qtermine pour tout𝑥dans son domaine de définition.

Ainsi,𝑓pheadqtermine pour toute valeur possible de head la tête de liste. La fonctionnelle map est récursive et s’appelle récursivement sur la queue tail de la liste, qui est de taille strictement plus petite que la liste complète liste. Sur une liste vide la fonctionnelle s’arrête bien, donc globalement la fonction termine bien.

Preuve de la correction :

Sur une liste vide,map [] f donne [] ce qui est bien correct. En raisonnant par récurrence, supposons avoir prouvé la correction de notre fonction map pour toute liste de taille inférieure ou égale à un certain 𝑛 P N fixé. Alors si liste est de taille 𝑛`1, elle s’écrit bien commeliste

= head :: tail avec tail de taille 𝑛, et donc l’appel à map liste fva construire la liste (f head) :: (map tail f). Par hypothèse de récurrence, map tail f est correct et produit la liste attendue, à laquelle on concatène f headen début de liste, donc on construit la liste correcte de taille 𝑛`1. Cela termine la récurrence, et donc la fonction mapest correcte pour toute taille de liste liste.

(2)

3. On note 𝐶𝑛 le nombre d’appels à la fonction map lors de l’appel map f liste pour une liste ('a list) de longueur 𝑛 PN. Déterminer 𝐶𝑛 pour tout𝑛 PN.

De même que pour la correction, on prouve facilement par récurrence que 𝐶0 “ 0 et 𝐶𝑛`1 “1`𝐶𝑛 donc𝐶𝑛𝑛 pour tout 𝑛P N.

Ex.2 Autour de l’alphabet et des majuscules et minuscules - C (30 minutes)

Écrire une fichier C colle10.cimportant stdio.h, string.h.

On rappelle qu’on compile ce fichier avec COMPILATEUR = gcc ou clang avec la ligne de commande suivante, puis on exécute le binaire produit avec la deuxième ligne (sans les dollars qui représentent le prompt de la ligne de commande du terminal) :

$ COMPILATEUR -O0 -Wall -Wextra -Wvla -Werror -fsanitize=address -fsanitize=undefined -pedantic -std=c11 -o colle10.exe colle10.c

$ ./colle10.exe

Si une ligne affiche un résultat qui vous semble bizarre, commenter le.

On rappelle qu’en C, le type charreprésente des entiers sur 8 bits, c’est-à-dire un octet, soit des entiers entre 0 et 255. Il est utilisé pour représenter les caractères ASCII étendu (256), qui peuvent être affiché à l’écran avec le drapeau %c dans unprintf, et sur lesquels on peut faire des opérations arithmétiques comme 'a'+1 qui donnera 'b'. En particulier, on peut faire des opérations et des comparaisons arithmétiques entre char, comme on le ferait avec des entiers.

Par contre, on utilise pas un entier comme un char et inversement.

4. Afficher ligne par ligne tous les caractères ASCII 128 imprimables en affichant leur valeur entière et le caractère associé, soit les caractères compris entre 32 et 126 (inclus), sous la forme suivante :

ASCII # 32 = ’ ’ ASCII # 33 = ’!’

...ASCII # 126 = ’~’

5. En observant que les caractères de 'A'à 'Z'se suivent, écrire une fonction

char lettre_suivante(char lettre) qui à'A' associe'B', à 'B'associe'C' etc, et à 'Z' associe 'A'.

6. Les caractères minuscules'a' à 'z'se suivent aussi. Écrire une fonction

char mise_en_majuscule(char lettre) qui à 'a' associe 'A'et ainsi de suite jusqu’à 'z' qui est associé à 'Z'. On supposera que lettre se trouve dans l’intervale entre 'A' et 'Z' ou entre 'a'et 'z'.

7. Faire une fonction inversechar mise_en_minuscule(char lettre) qui met en minuscule une lettre, sous les mêmes hypothèses.

(3)

8. En utilisant la fonction précédente et le fait qu’une chaîne de caractère (de typechar[] et pas char*) n’est rien d’autre qu’un tableau dechar, écrire une fonction

void mise_nom_en_majuscule(char nom[]) qui agit par effet de bord pour mettre nom entièrement en majuscule.

9. Faire de même pour void mise_prenom_commencant_majuscule(char prenom[]) qui agit par effet de bord pour mettre la première lettre en majuscule et les suivantes en minuscule.

On aura par exemple les résultats suivants : char nom[] = "dupont";

mise_nom_en_majuscule(nom);

printf("mise_nom_en_majuscule(\"%s\") -> \"%s\"", "dupont", nom);

// affiche : mise_nom_en_majuscule("dupont") -> "DUPONT"

char prenom[] = "TiNtIN";

mise_prenom_commencant_majuscule(prenom);

printf("mise_prenom_commencant_majuscule(\"%s\") -> \"%s\"", "TiNtIN", prenom);

// affiche : mise_prenom_commencant_majuscule("TiNtIN") -> "Tintin"

Correction :

#include <stdio.h>

#include <string.h>

char lettre_suivante(char c) { if (c >= ’A’ && c < ’Z’) {

return c + 1;

} else if (c == ’Z’) { return ’A’;

} else {

// au cas où, on renvoie quand même un char non modifié return c;

} }

char mise_en_majuscule(char lettre) { if (lettre >= ’a’ && lettre <= ’z’) {

return lettre + (’A’ - ’a’);

} else {

// au cas où, on renvoie quand même un char non modifié return lettre;

} }

char mise_en_minuscule(char lettre) { if (lettre >= ’A’ && lettre <= ’Z’) {

(4)

return lettre + (’a’ - ’A’);

} else {

// au cas où, on renvoie quand même un char non modifié return lettre;

} }

void nom_en_majuscule(char nom[]) {

for(size_t i = 0; i < strlen(nom); i += 1) {

printf("nom[%li] = mise_en_majuscule(%c)\n", i, nom[i]);

nom[i] = mise_en_majuscule(nom[i]);

} }

void prenom_commencant_majuscule(char prenom[]) { prenom[0] = mise_en_majuscule(prenom[0]);

for(size_t i = 1; i < strlen(prenom); i += 1) { prenom[i] = mise_en_minuscule(prenom[i]);

} }

int main() { // Question 4.

for (char c = 32; c <= 126; c += 1) { printf("ASCII # %i = ’%c’\n", c, c);

}// Question 5.

for (char c = ’A’; c <= ’Z’; c += 1) {

printf("lettre_suivante(’%c’) = ’%c’\n", c, lettre_suivante(c));

}// Question 6.

for (char c = ’a’; c <= ’z’; c += 1) {

printf("mise_en_majuscule(’%c’) = ’%c’\n", c, mise_en_majuscule(c));

}// Question 7.

for (char c = ’A’; c <= ’Z’; c += 1) {

printf("mise_en_minuscule(’%c’) = ’%c’\n", c, mise_en_minuscule(c));

}// Question 8.

char nom[] = "dupont";

nom_en_majuscule(nom);

printf("nom_en_majuscule(\"%s\") -> \"%s\"\n", "dupont", nom);

// Question 8.

char prenom[] = "TiNtIN";

prenom_commencant_majuscule(prenom);

printf("prenom_commencant_majuscule(\"%s\") -> \"%s\"\n", "TiNtIN", prenom);

}

(5)

La sortie ressemblera à ça (en tronquant les lignes que l’on devine) : ASCII # 32 = ’ ’

ASCII # 33 = ’!’

ASCII # 34 = ’"’

ASCII # 35 = ’#’

ASCII # 36 = ’$’

ASCII # 37 = ’%’

ASCII # 38 = ’&’

ASCII # 39 = ’’’

ASCII # 40 = ’(’

ASCII # 41 = ’)’

ASCII # 42 = ’*’

ASCII # 43 = ’+’

ASCII # 44 = ’,’

ASCII # 45 = ’-’

ASCII # 46 = ’.’

ASCII # 47 = ’/’

ASCII # 48 = ’0’

ASCII # 49 = ’1’

ASCII # 50 = ’2’

ASCII # 51 = ’3’

ASCII # 52 = ’4’

ASCII # 53 = ’5’

ASCII # 54 = ’6’

ASCII # 55 = ’7’

ASCII # 56 = ’8’

ASCII # 57 = ’9’

ASCII # 58 = ’:’

ASCII # 59 = ’;’

ASCII # 60 = ’<’

ASCII # 61 = ’=’

ASCII # 62 = ’>’

ASCII # 63 = ’?’

ASCII # 64 = ’@’

ASCII # 65 = ’A’

ASCII # 66 = ’B’

ASCII # 67 = ’C’

ASCII # 68 = ’D’

ASCII # 69 = ’E’

ASCII # 70 = ’F’

ASCII # 71 = ’G’

ASCII # 72 = ’H’

ASCII # 73 = ’I’

ASCII # 74 = ’J’

ASCII # 75 = ’K’

ASCII # 76 = ’L’

ASCII # 77 = ’M’

(6)

ASCII # 78 = ’N’

ASCII # 79 = ’O’

ASCII # 80 = ’P’

ASCII # 81 = ’Q’

ASCII # 82 = ’R’

ASCII # 83 = ’S’

ASCII # 84 = ’T’

ASCII # 85 = ’U’

ASCII # 86 = ’V’

ASCII # 87 = ’W’

ASCII # 88 = ’X’

ASCII # 89 = ’Y’

ASCII # 90 = ’Z’

ASCII # 91 = ’[’

ASCII # 92 = ’\’

ASCII # 93 = ’]’

ASCII # 94 = ’^’

ASCII # 95 = ’_’

ASCII # 96 = ’‘’

ASCII # 97 = ’a’

ASCII # 98 = ’b’

ASCII # 99 = ’c’

ASCII # 100 = ’d’

ASCII # 101 = ’e’

ASCII # 102 = ’f’

ASCII # 103 = ’g’

ASCII # 104 = ’h’

ASCII # 105 = ’i’

ASCII # 106 = ’j’

ASCII # 107 = ’k’

ASCII # 108 = ’l’

ASCII # 109 = ’m’

ASCII # 110 = ’n’

ASCII # 111 = ’o’

ASCII # 112 = ’p’

ASCII # 113 = ’q’

ASCII # 114 = ’r’

ASCII # 115 = ’s’

ASCII # 116 = ’t’

ASCII # 117 = ’u’

ASCII # 118 = ’v’

ASCII # 119 = ’w’

ASCII # 120 = ’x’

ASCII # 121 = ’y’

ASCII # 122 = ’z’

ASCII # 123 = ’{’

ASCII # 124 = ’|’

(7)

ASCII # 125 = ’}’

ASCII # 126 = ’~’

lettre_suivante(’A’) = ’B’

lettre_suivante(’B’) = ’C’

...lettre_suivante(’Y’) = ’Z’

lettre_suivante(’Z’) = ’A’

mise_en_majuscule(’a’) = ’A’

mise_en_majuscule(’b’) = ’B’

...mise_en_majuscule(’y’) = ’Y’

mise_en_majuscule(’z’) = ’Z’

mise_en_minuscule(’A’) = ’a’

mise_en_minuscule(’B’) = ’b’

...mise_en_minuscule(’Y’) = ’y’

mise_en_minuscule(’Z’) = ’z’

nom[0] = mise_en_majuscule(d) nom[1] = mise_en_majuscule(u) nom[2] = mise_en_majuscule(p) nom[3] = mise_en_majuscule(o) nom[4] = mise_en_majuscule(n) nom[5] = mise_en_majuscule(t)

nom_en_majuscule("dupont") -> "DUPONT"

prenom_commencant_majuscule("TiNtIN") -> "Tintin"

Références

Documents relatifs

L'avantage de la méthode boothroyd est complètement prédictive rapide et qu'elle peut être adaptée à différents matériaux, et nous avons conclu avec se modèle

• premièrement c’est avoir une idée approfondie sur l’application de l’approche théorique dans le milieu professionnel ce qui nous permettra de comprendre et de maîtriser

[r]

Le fichier joint contient les donn´ ees permettant de tracer le spectre d’´ emission du soleil (i.e.. En utilisant la fonction indice max(liste) d´

Pour rétablir les paramètres d'origine d'un affichage, sélectionnez le dossier de messages concerné puis, dans l'onglet View, cliquez sur le bouton Reset View du groupe Current

déterminer l’ensemble des points M’’ lorsque M décrit la

b-En déduire que la suite (  n ) est strictement croissante et qu’elle est convergente.. En déduire

Les matières premières entrant dans la production du kitoza : (Ireo akora ampiasaina amin’ny famokarana kitoza 6.1 Quels sont les différents types de viande que vous utilisez pour