Apprentissage de la programmation avec OCaml

Catherine Dubois & Valérie Ménissier-Morain

Édition Hermès Sciences

Table des matières

 
Avant-propos 13
 
 
Chapitre 1.  Introduction 17
 
         1.1. Pourquoi étudier l'informatique (et en particulier la programmation) ?17
         1.2. Qu'est-ce-que la programmation ?18
         1.3. Les étapes du développement d'un programme18
                 1.3.1. Première étape : la spécification.18
                 1.3.2. Deuxième étape : la recherche d'un algorithme pour résoudre le problème19
                 1.3.3. Troisième étape : la transcription de l'algorithme dans un langage de programmation ou « écriture du programme »19
                 1.3.4. Quatrième étape : la validation du programme20
                 1.3.5. Récapitulatif20
                 1.3.6. Exemple21
         1.4. Les langages de programmation21
         1.5. Pourquoi OCaml ?23
         1.6. Comment se procurer OCaml ?23
         1.7. Plan de l'ouvrage23
         1.8. Logiciels utilisés dans cet ouvrage24
 
PREMIÈRE PARTIE. ÉLÉMENTS DE PROGRAMMATION 25
 
Chapitre 2.  Introduction à OCaml 27
 
         2.1. Notions d'expression et de valeur27
         2.2. Les types de base28
                 2.2.1. Le type int28
                 2.2.2. Le type float28
                 2.2.3. Le type bool29
                 2.2.4. Le type char29
                 2.2.5. Le type string30
         2.3. La boucle interactive de OCaml ou comment utiliser OCaml?30
         2.4. Définitions33
                 2.4.1. Notion d'identificateur33
                 2.4.2. Définitions globales33
                 2.4.3. Définitions locales37
         2.5. Expressions conditionnelles41
         2.6. De l'usage des parenthèses42
 
Chapitre 3.  Fonctions 43
 
         3.1. Fonctions d'une variable43
                 3.1.1. Introduction43
                 3.1.2. Définition de fonctions44
                 3.1.3. Exemples45
                 3.1.4. Application d'une fonction46
         3.2. Fonctions à plusieurs paramètres47
                 3.2.1. Définition d'une fonction à plusieurs paramètres47
                 3.2.2. Application d'une fonction à plusieurs paramètres48
         3.3. Composition de fonctions49
         3.4. Définition locale de fonction50
         3.5. Portée statique51
         3.6. Introduction au typage d'une fonction52
         3.7. Restriction du domaine de définition d'une fonction54
         3.8. Un exemple complet : écrire les nombres en lettres55
                 3.8.1. Les fonctions unité, dizaine, centaine et millier58
                 3.8.2. La fonction écrire_millier59
                 3.8.3. La fonction écrire_centaine60
                 3.8.4. La fonction écrire_dizaine_unité60
 
Chapitre 4.  Fonctions récursives 65
 
         4.1. Notion de récursivité66
         4.2. Définition d'une fonction récursive en OCaml67
                 4.2.1. Fonctions simplement récursives67
                 4.2.2. Fonctions mutuellement récursives69
         4.3. Évaluation d'un appel à une fonction récursive70
         4.4. Propriétés des fonctions récursives73
         4.5. Méthode de décomposition récursive75
                 4.5.1. Méthode générale75
                 4.5.2. Un exemple simple : le calcul du reste de la division euclidienne de deux nombres naturels76
                 4.5.3. Un exemple magique : les tours de Hanoi76
 
Chapitre 5.  Listes 79
 
         5.1. Syntaxe - Typage - Évaluation79
                 5.1.1. Définition79
                 5.1.2. Syntaxe et évaluation80
                 5.1.3. Typage80
                 5.1.4. L'opérateur ::81
         5.2. Fonctions simples sur les listes82
         5.3. Filtrage87
                 5.3.1. Vocabulaire et définitions87
                 5.3.2. Récapitulatif des formes possibles de filtre89
                 5.3.3. Mise en correspondance d'un filtre avec une valeur90
                 5.3.4. Évaluation d'une expression de filtrage90
         5.4. Fonctions récursives sur les listes91
                 5.4.1. Longueur d'une liste91
                 5.4.2. Recherche d'un élément dans une liste92
                 5.4.3. Dernier élément d'une liste93
                 5.4.4. Recherche du plus petit élément d'une liste94
                 5.4.5. Intervalle d'entiers94
                 5.4.6. Extraction des entiers pairs d'une liste d'entiers95
                 5.4.7. Remplacement de certains éléments95
                 5.4.8. Concaténation de deux listes96
         5.5. Manipulation de listes triées96
                 5.5.1. Recherche d'un élément dans une liste triée97
                 5.5.2. Insertion dans une liste triée97
         5.6. Algorithmes de tri99
                 5.6.1. Tri par insertion99
                 5.6.2. Tri par sélection100
                 5.6.3. Tri par fusion100
                 5.6.4. Comparaison de ces différentes méthodes de tri103
 
Chapitre 6.  Types produits (paires et n-uplets) 107
 
         6.1. Produit de deux types107
         6.2. Construction des paires (syntaxe, typage, évaluation)108
         6.3. Quelques exemples simples de fonctions manipulant des paires108
         6.4. Fonction récursive retournant une paire111
         6.5. Filtrage des couples112
         6.6. Listes et paires112
                 6.6.1. Listes de vecteurs113
                 6.6.2. Listes d'associations113
         6.7. Généralisation des couples : les n-uplets115
         6.8. Fonctions à plusieurs arguments versus fonctions à un argument n-uplet116
         6.9. Un exemple plus conséquent : la date du lendemain117
 
Chapitre 7.  Types enregistrements 121
 
         7.1. Déclaration d'un type enregistrement122
         7.2. Création et manipulation d'enregistrements124
         7.3. Accès aux composantes d'un enregistrement124
         7.4. Filtrage des enregistrements126
         7.5. Un petit exemple : les notes d'un étudiant127
         7.6. Un exemple plus conséquent: les nombres rationnels129
                 7.6.1. Représentation non normalisée (sans simplification systématique)129
                 7.6.2. Simplifier les rationnels130
                 7.6.3. Représentation normalisée131
                 7.6.4. Simplifier en calculant132
 
Chapitre 8.  Types sommes 135
 
         8.1. Exemple de la définition du type des formes géométriques135
         8.2. Déclaration d'un type somme137
         8.3. Construction des expressions d'un type somme (syntaxe, typage, évaluation)138
         8.4. Filtrage sur les types sommes139
                 8.4.1. Manipulations de formes139
                 8.4.2. Bilan sur les filtres141
         8.5. Modélisation d'un jeu de tarot142
                 8.5.1. Définition des cartes ordinaires142
                 8.5.2. Définition privilégiant la nature des cartes143
                 8.5.3. Définition préservant la symétrie nature/couleur144
                 8.5.4. Définition du type des cartes144
 
Chapitre 9.  Types récursifs 147
 
         9.1. Polynômes à une indéterminée147
         9.2. Cocktails152
         9.3. Expressions arithmétiques156
         9.4. Arbres159
         9.5. Arbres binaires de recherche164
                 9.5.1. Présentation164
                 9.5.2. Recherche dans un arbre binaire de recherche165
                 9.5.3. Parcours d'un arbre binaire de recherche167
                 9.5.4. Insertion dans un arbre binaire de recherche168
                 9.5.5. Construction d'un arbre binaire de recherche168
         9.6. Types mutuellement récursifs169
 
Chapitre 10.  Introduction à l'ordre supérieur 171
 
         10.1. Fonctions numériques172
                 10.1.1. Calcul de la pente d'une fonction en 0172
                 10.1.2. Dérivée d'une fonction172
                 10.1.3. Calcul d'un zéro d'une fonction par une méthode dichotomique174
                 10.1.4. Composition de fonctions176
         10.2. Itération d'une fonction177
                 10.2.1. Calcul du n-ième terme d'une suite définie récursivement177
                 10.2.2. Sommation178
                 10.2.3. Application d'une fonction à tous les éléments d'une liste179
                 10.2.4. Itérer une fonction sur une liste180
         10.3. Fonctions paramétrées par un prédicat184
                 10.3.1. Extraction d'éléments dans une liste184
                 10.3.2. Insertion dans une liste triée, tri d'une liste185
 
Chapitre 11.  Données mutables 189
 
         11.1. Introduction à la programmation impérative189
                 11.1.1. Regard en arrière sur la programmation fonctionnelle189
                 11.1.2. Valeurs modifiables ou mutables190
         11.2. Les références191
         11.3. Les champs mutables dans les enregistrements194
                 11.3.1. Déclaration, création, consultation et modification194
                 11.3.2. Retour sur les références198
                 11.3.3. Synonymie, partage199
         11.4. Tableaux200
                 11.4.1. Vecteurs201
                 11.4.2. Analogie chaîne de caractères, vecteur203
                 11.4.3. Matrices205
         11.5. Impression à l'écran207
         11.6. Séquences209
         11.7. Boucles211
                 11.7.1. Boucle while211
                 11.7.2. Boucle for211
                 11.7.3. La factorielle : version « impérative »213
                 11.7.4. Boucles et tableaux : quelques exemples214
         11.8. Résolution de systèmes linéaires par l'algorithme du pivot de Gauß 219
         11.9. Recherche et tri dans un vecteur223
                 11.9.1. Recherche dans un vecteur224
                 11.9.2. Tris226
         11.10. Fichiers et opérations de base232
 
Chapitre 12.  Exceptions 239
 
         12.1. Fonctions partielles et exceptions239
         12.2. Déclaration d'une exception240
         12.3. Levée d'une exception242
         12.4. Traitement d'une exception244
         12.5. Exception et ordre d'évaluation247
         12.6. Utilisation avancée des exceptions248
                 12.6.1. Recherche d'un élément dans un tableau249
                 12.6.2. Acquisition sûre de données250
                 12.6.3. Un algorithme à essais successifs251
 
Chapitre 13.  Introduction à la modularité 253
 
         13.1. Développement de gros logiciels253
         13.2. Modules255
                 13.2.1. Définition d'un module255
                 13.2.2. Impacts sur le développement de logiciels255
         13.3. Syntaxe des modules257
                 13.3.1. Forme des déclarations dans l'interface257
                 13.3.2. Un premier exemple de module258
                 13.3.3. Modules de la bibliothèque standard258
         13.4. Utilisation des ressources d'un module260
                 13.4.1. Notation pointée260
                 13.4.2. La directive open261
         13.5. Compilation séparée261
         13.6. Utilisation interactive des modules264
         13.7. Types abstraits264
 
Chapitre 14.  Choix des structures de données 269
 
         14.1. Structures de données linéaires269
                 14.1.1. Comparaison vecteur-liste269
                 14.1.2. Représentation des piles271
                 14.1.3. Représentation des files273
                 14.1.4. Listes chaînées277
                 14.1.5. Retour sur la représentation des files283
                 14.1.6. Conclusion sur les structures de données linéaires284
         14.2. Structures de données arborescentes284
                 14.2.1. Arbres284
                 14.2.2. Files de priorité289
                 14.2.3. Tas290
         14.3. Autres structures de données296
 
DEUXIÈME PARTIE. QUELQUES DÉVELOPPEMENTS COMPLETS 297
 
Chapitre 15.  Alignement de séquences ADN 299
 
         15.1. Le problème posé299
         15.2. Quelques éléments de vocabulaire sur les séquences300
         15.3. Représentation des séquences d'ADN301
         15.4. Opérations d'édition301
         15.5. Alignement302
                 15.5.1. Affichage d'un alignement302
                 15.5.2. Application d'un alignement à une séquence304
                 15.5.3. Coût d'un alignement304
         15.6. Alignement optimal et distance d'édition305
                 15.6.1. Calcul de la distance d'édition306
                 15.6.2. Calcul d'un alignement de coût optimal309
         15.7. Un algorithme efficace d'alignement de deux séquences311
                 15.7.1. Calcul de la matrice D312
                 15.7.2. Recherche d'un alignement optimal315
         15.8. Conclusion317
 
Chapitre 16.  Vérification de formules logiques 319
 
         16.1. Le rôle de la logique en informatique319
         16.2. Le calcul propositionnel319
                 16.2.1. Syntaxe du calcul propositionnel320
                 16.2.2. Représentation des formules en OCaml321
                 16.2.3. Tables de vérité322
                 16.2.4. Interprétation d'une formule323
                 16.2.5. Tautologie/contradiction324
         16.3. Analyse syntaxique de formules328
                 16.3.1. Syntaxe concrète des formules329
                 16.3.2. Conception descendante de l'analyseur syntaxique330
         16.4. Preuve de formules propositionnelles en déduction naturelle340
                 16.4.1. Preuve formelle et règles de déduction341
                 16.4.2. Tactique de preuve et vérification343
                 16.4.3. Un exemple346
         16.5. Réalisation en OCaml de l'assistant à la preuve348
                 16.5.1. Type des tactiques348
                 16.5.2. Représentation d'un but349
                 16.5.3. Affichage d'un but349
                 16.5.4. Application d'une tactique à un but353
                 16.5.5. Analyse syntaxique d'une tactique357
                 16.5.6. Vérification interactive360
         16.6. Conclusion363
 
Chapitre 17.  Un exemple graphique : le jeu COURT-CIRCUIT 365
 
         17.1. Description du jeu365
         17.2. Représentation du jeu366
         17.3. Remplissage de la zone de jeu369
                 17.3.1. Générateur aléatoire369
                 17.3.2. Principe de remplissage de la zone de jeu369
                 17.3.3. Création du tableau: appariement des couleurs369
                 17.3.4. Permutation du tableau: mélange des couleurs370
                 17.3.5. Affichage textuel de la zone de jeu371
         17.4. Détection d'un circuit valide et suppression d'un couple de pièces372
                 17.4.1. Détection de circuits valides372
                 17.4.2. Angles d'un circuit378
         17.5. Affichage graphique statique de la zone de jeu et des circuits380
                 17.5.1. Présentation de la bibliothèque graphique380
                 17.5.2. Dessin des pièces383
                 17.5.3. Affichage graphique de la zone de jeu388
                 17.5.4. Affichage graphique des circuits389
                 17.5.5. Effaçage d'une pièce sélectionnée et d'un circuit390
         17.6. Affichage graphique avec gestion de l'action du joueur391
                 17.6.1. Premiers pas en gestion évènementielle391
                 17.6.2. Interaction avec le joueur393
                 17.6.3. La version de base du jeu395
                 17.6.4. Version de base modulaire397
         17.7. Enrichissement du jeu avec des niveaux401
                 17.7.1. Représentation du jeu402
                 17.7.2. Circuits405
                 17.7.3. Interaction avec le joueur405
                 17.7.4. Affichage du jeu405
                 17.7.5. Lancement du jeu408
         17.8. Aide au joueur409
                 17.8.1. Suggestion409
                 17.8.2. Backtrack411
                 17.8.3. Arrêt entre les niveaux412
         17.9. Jeu contre la montre et pause414
                 17.9.1. Une première version à temps compté415
                 17.9.2. Version avec indication de la progression du jeu416
                 17.9.3. Version avec pause419
         17.10. Scores, table des meilleurs scores421
                 17.10.1. Scores422
                 17.10.2. Table des meilleurs scores424
                 17.10.3. Fin du jeu431
         17.11. Améliorations433
         17.12. Conclusion438
 
Bibliographie 439
 
 
Index 441