Algorithmique & Programmation Orientée Objet Semestre 2 ST Structuration des programmes en sous-algorithmes
Cours | Exercices PDL - Corrections | Exercices Java
Exercice n°1: Sous-algorithmes "simples" a) Ecrire un sous-algorithme de calcul du sinus d'un angle donné en degrés. La fonction développée possède un paramètre d'entête de type réel passé en entrée pour l'angle (en degré). Elle retourne un réel: le sinus de l'angle. Une alternative aurait été de développer une fonction sans paramètre retourné, mais avec un paramètre d'entête supplémentaire passé en sortie.
Sinus.lda { Calcul du du sinus d'un angle en degres } constante reel PI <- 3.14159 reel fonction sinus(-> réel angle) reel sn sn <- sin(angle*PI/180.0) retourner sn fin fonction Exemple d'exécution
b) Ecrire un sous-algorithme de test si un caractère est alphabétique (minuscule ou majuscule). La fonction développée possède un paramètre d'entête passé en entrée de type caractère pour le caractère à tester. Elle retourne un booléen: vrai ou faux en fonction du résultat du test. Une alternative aurait été de développer une fonction sans paramètre retourné, mais avec un paramètre d'entête supplémentaire passé en sortie.
TestCaractereAlphabetique.lda { Test si un caractere est alphabetique ou non } booleen fonction estAlphabetique(-> caractere c) booleen res si ( ( c >= 'a' ) et ( c <= 'z' ) ) ou ( ( c >= 'A' ) et ( c <= 'Z' ) ) alors res <- vrai sinon res <- faux fsi retourner res fin fonction Exemple d'exécution
c) Ecrire un sous-algorithme de lecture au clavier d'un nombre entier positif. Si l'utilisateur frappe une valeur non positive, il devra être sollicité de nouveau jusqu'à ce qu'il tape une valeur admissible. La fonction développée ne possède pas de paramètre d'entête. Elle retourne un entier: la valeur positive saisie. Une alternative aurait été de développer une fonction sans paramètre retourné, mais avec un paramètre d'entête passé en sortie.
LectureEntierPositif.lda { Lecture au clavier d'une valeur entiere } { positive et retour } entier fonction lectureEntierPositif() entier valeur valeur <- Clavier.sasirEntier() tant que valeur < 0 faire afficherln("Erreur!!! Veuillez ressaisir) valeur <- saisir() fait retourner valeur fin fonction Exemple d'exécution
d) Ecrire un sous-algorithme de lecture au clavier d'un nombre réel compris dans un intervalle [min, max]. Si l'utilisateur frappe une valeur en dehors de l'intervalle, il devra être sollicité de nouveau jusqu'à ce qu'il tape une valeur admissible. La fonction développée possède deux paramètres d'entête réels passés en entrée: les valeurs min et max. Elle retourne un réel: la valeur saisie dans l'intervalle [min,max]. Une alternative aurait été de développer une fonction sans paramètre retourné, mais avec un paramètre d'entête supplémentaire passé en sortie.
LectureReelDansIntervalle.lda { Lecture au clavier d'une valeur reelle } { comprise dans un intervalle et retour } reel fonction lectureReelDansIntervalle(-> reel min,-> reel max) reel valeur valeur <- saisir() tant que valeur < min ou valeur > max faire afficherln("Erreur!!! Veuillez ressaisir) valeur <- saisir() fait retourner valeur fin fonction Exemple d'exécution
e) Ecrire un sous-algorithme d'affichage en hexadécimal d'un nombre entier. On considérera que le nombre à afficher est compris dans l'intervalle [0,255]. La fonction développée possède un paramètre d'entête de type entier passé en entrée: la valeur à afficher en hexadécimal. Elle retourne aucune valeur car son but est uniquement de réaliser un affichage. Une fonction affichageChiffreHexadecimal a été développée pour afficher un chiffre hexadécimal ('0' à '9' puis 'A' à 'F') suivant sa valeur décimale (0 à 15). Le nombre entier passé en paramètre étant compris entre 0 et 255, deux chiffres hexadécimaux sont à afficher. La fonction affichageChiffreHexadecimal est appelée 2 fois: une fois pour chacun des 2 chiffres.
AffichageHexadecimal.lda { Affichage hexadecimal d'un entier compris entre 0 et 255 } action affichageHexadecimal(-> entier v) entier chiffreHaut entier chiffreBas chiffreHaut <- v/16 chiffreBas <- v modulo 16 affichageChiffreHexadecimal(chiffreHaut) affichageChiffreHexadecimal(chiffreBas) fin action { Affichage hexadecimal d'un chiffre } action affichageChiffreHexadecimal(-> entier chiffre) dans le cas de chiffre 10 : afficher('A') 11 : afficher('B') 12 : afficher('C') 13 : afficher('D') 14 : afficher('E') 15 : afficher('F') autre cas : afficher(chiffre) fcas fin action Exemple d'exécution
f) Ecrire un sous-algorithme de calcul de la valeur de sin(a) au voisinage de 0.0 par développement limité. La formule de calcul est sin(a) = a - a3/3! + a5/5! - a7/7! + a9/9! - ... +/- an/n! (a en radians) La fonction développée possède un paramètre d'entête de type réel passé en entrée: la valeur de l'angle (en radians) pour laquelle on calcule le sinus. Elle retourne une valeur de type réel: la valeur de sinus calculée. Une alternative aurait été de développer une fonction sans paramètre retourné, mais avec un paramètre d'entête supplémentaire passé en sortie. Pour optimiser l'exécution, toutes les puissances et toutes les factorielles ne sont pas calculées intégralement. Chaque terme de la suite est calculé à partir du terme précédent. Le terme 1 est égal à a (a/1). Ensuite chaque terme i est égal au terme i-1 multiplié par a*a et divisé par i*2-2 et par i*2-1. Le développement limité est obtenu par somme d'un certain nombre de termes. On notera que, dans l'implantation, plutôt que de numéroter les termes 1, 2, 3, 4, 5, ..., on a préféré les numéroter 1, 3, 5, 7, 9, ...
DeveloppementLimiteSinus.lda { Calcul de la valeur de sin(a) au voisinage de 0.0 } { Utilisation du developpement limite } { Les valeurs a et n sont donnees } reel fonction sinus(-> reel a,-> entier n) reel sn reel terme entier i terme <- a sn <- a pour i de 3 à n pas 2 faire terme <- -terme*a*a/(i*(i-1)) sn <- sn + terme fait retourner sn fin fonction Exemple d'exécution
Exercice n°2: Sous-algorithmes avec données agrégées a) Ecrire un sous-algorithme de calcul du sinus et du cosinus d'un angle donné en degrés. Première alternative: Développer une fonction avec un paramètre d'entête de type réel passé en entrée pour l'angle (en degré) et deux paramètres d'entête passés en sortie pour les deux valeurs calculées. Deuxième alternative: Développer une fonction avec un paramètre d'entête de type réel passé en entrée pour l'angle (en degré) et un paramètre d'entête passé en sortie agrégeant deux réels (un pour le sinus, un pour le cosinus) (Solution non développée ci-dessous). Troisième alternative: Développer une fonction avec un paramètre d'entête de type réel passé en entrée pour l'angle (en degré) et une valeur retournée agrégeant deux réels (un pour le sinus, un pour le cosinus).
CosinusEtSinus.lda (Solution sans type agrégé) { Calcul du cosinus et du sinus d'un angle } { donne en degres } action calculCosinusEtSinus(-> reel angle,reel cosinus ->,reel sinus ->) reel a a <- angle*3.1415926535897932/180.0 cosinus <- cos(a) sinus <- sin(a) fin action Exemple d'exécution
CosinusEtSinusAvecStructure.lda (Solution avec type agrégé) { Type agrege de stockage du cosinus } { et du sinus d'un angle } structure cosinusEtSinus reel cosinus <- 1.0 reel sinus <- 0.0 fin structure { Calcul du cosinus et du sinus d'un angle } { donne en degres } cosinusEtSinus fonction calculCosinusEtSinus(-> reel angle) reel a cosinusEtSinus res a <- angle*3.1415926535897932/180.0 res.cosinus <- cos(a) res.sinus <- sin(a) retourner res fin fonction Exemple d'exécution
b) Ecrire un sous-algorithme de test de l'inclusion d'un point de coordonnées (x,y) à l'intérieur d'un cercle de rayon r et de centre (cx,cy). Première alternative: Développer une fonction avec cinq paramètres d'entête de type réel passés en entrée pour l'abscisse et l'ordonnée du point testé, le rayon, l'abscisse et l'ordonnée du centre du cercle. Elle retourne une valeur de type booléen: vrai ou faux pour inclusion ou non inclusion. Seconde alternativer: Structurer les données et développer une fonction avec deux paramètres d'entête agrégés de type position2D pour le point testé, et cercle2D pour le cercle. Elle retourne une valeur de type booléen: vrai ou faux pour inclusion ou non inclusion.
TestInclusion.lda (solution sans type agrégé) { Test de l'inclusion d'un point dans un cercle } { Les coordonnees du point sont donnees } { ainsi que le rayon et les coordonnees } { du centre du cercle } booleen fonction testInclusion(-> reel x,-> reel y,-> reel rayon,-> reel cx,-> reel cy) booleen inclus reel distance distance <- sqrt((x-cx)*(x-cx)+(y-cy)*(y-cy)) si distance < rayon alors inclus <- vrai sinon inclus <- faux fsi retourner inclus fin fonction Exemple d'exécution
TestInclusionAvecStructure.lda (solution avec types agrégés) { Type agrege de stockage d'une position du plan } structure position2D reel x <- 0.0 reel y <- 0.0 fin structure { Type agrege de stockage d'un cercle du plan } structure cercle2D position2D centre reel rayon <- 1.0 fin structure { Test de l'inclusion d'une position du plan } { dans un cercle du plan } booleen fonction testInclusion(-> position2D p,-> cercle2D c) reel dx reel dy reel distance booleen inclus dx <- p.x-c.centre.x dy <- p.y-c.centre.y distance <- sqrt(dx*dx+dy*dy) inclus <- (distance <= c.rayon) retourner inclus fin fonction Exemple d'exécution
c) Ecrire un sous-algorithme de calcul de la surface d'un rectangle du plan à cotés parallèles aux axes. Le rectangle est représenté par la position de 2 sommets opposés du rectangle. Première alternative: Développer une fonction avec quatre paramètres d'entête de type réel passés en entrée pour l'abscisse et l'ordonnée du premier sommet et l'abscisse et l'ordonnée du second sommet. Elle retourne une valeur de type réel: la surface. Seconde alternativer: Structurer les données et développer une fonction avec un paramètre d'entête agrégé de type rectangle2D passé en entrée. Elle retourne une valeur de type réel: la surface.
SurfaceRectangle.lda (solution sans type agrégé) { Calcul de la surface d'un rectangle } { Les coordonnees de deux coins opposes } { sont donnees } entier fonction surfaceRectangle(-> reel px1,-> reel py1,-> reel px2,-> reel py2) reel surface surface <- abs(px2-px1)*abs(py2-py1) retourner surface fin fonction Exemple d'exécution
SurfaceRectangleAvecStructure.lda (solution avec types agrégés) { Type agrege de stockage d'une position du plan } structure position2D reel x <- 0.0 reel y <- 0.0 fin structure { Type agrege de stockage d'un rectangle du plan } structure rectangle2D position2D p1 position2D p2 fin structure { Calcul de la surface d'un rectangle 2D } entier fonction surfaceRectangle(-> rectangle2D r) reel surface surface <- abs(r.p2.x-r.p1.x)*abs(r.p2.y-r.p1.y) retourner surface fin fonction Exemple d'exécution
Exercice n°1fbis: Sous-algorithme à plusieurs niveaux Reprendre l'exercice 1f en programmant le calcul du développement limité avec utilisation de fonctions pour les calculs de puissance et de factoriel.
DeveloppementLimiteSinusAvecFonctions.lda { Calcul de la puissance entiere d'un reel } { Les valeurs a reelle et n entiere sont donnees } reel fonction puissance(-> reel a,-> entier n) reel res entier i res <- a pour i de 1 à n-1 faire res <- res*a fait retourner res fin fonction { Calcul de n! } { La valeur n entiere est donnee } entier fonction factoriel(-> entier n) entier fct entier i fct <- 1 pour i de 2 à n faire fct <- fct*i fait retourner fct fin fonction { Calcul de la valeur de sin(a) au voisinage de 0.0 } { Utilisation du developpement limite } { Les valeurs a et n sont donnees } reel fonction sinus(-> reel a,-> entier n) reel sn reel signe entier i signe <- -1.0 sn <- a pour i de 3 à n pas 2 faire sn <- sn + puissance(a,i)/factoriel(i) signe <- -signe fait retourner sn fin fonction Exemple d'exécution
Exercice n°3: Sous-algorithmes à plusieurs niveaux et données agrégées a) Ecrire un sous-algorithme de test si une année est bissextile. La fonction développée possède un paramètre d'entête de type entier passé en entrée pour l'année testée. Elle retourne un booléen: vrai ou faux en fonction de la bissextilité de l'année.
TestBissextile.lda { Test si une annee est bissextile } { version 1 } booleen fonction estBissextile(-> entier annee) booleen res si annee modulo 400 == 0 alors res <- vrai sinon si annee modulo 100 == 0 alors res <- faux sinon si annee modulo 4 == 0 alors res <- vrai sinon res <- faux fsi fsi fsi retourner res fin fonction { version 2 } booleen fonction estBissextile(-> entier annee) booleen res si ( annee modulo 400 == 0 ) ou ( ( annee modulo 100 <> 0 ) et ( annee modulo 4 == 0 ) ) alors res <- vrai sinon res <- faux fsi retourner res fin fonction Exemple d'exécution
b) Ecrire un sous-algorithme de calcul du nombre de jours d'un mois codé sous la forme d'un nombre. La fonction développée possède deux paramètres d'entête de type entier passés en entrée pour le mois et l'année testés. Elle retourne un entier: le nombre de jours du mois.
NombreJoursMois.lda { Calcul du nombre de jours d'un mois } { Si le numero de mois est invalide, } { la fonction retourne -1 } entier fonction nombreJoursMois(-> entier mois,-> entier annee) entier res dans le cas de mois 2 : si estBissextile(annee) alors res <- 29 sinon res <- 28 fsi 4 : 6 : 9 : 11 : res <- 30 1 : 3 : 5 : 7 : 8 : 10 : 12 : res <- 31 autre cas : res <- -1 fcas retourner res fin fonction Exemple d'exécution
c) Ecrire un sous-algorithme de calcul de la date du jour suivant immédiatement une date codée sous la forme jour-mois-année en nombres. Solution 1: La fonction développée possède un paramètre d'entête passé en entrée de type date. Elle retourne une date: la date correspondant au jour suivant la date passée en entête. Solution 2: L'action développée possède deux paramètres d'entête. Le premier est passé en entrée et est de type date. Le second est passé en sortie et est de type date. Le second paramètre est destiné à recueillir la date calculée
JourSuivant.lda structure date entier jour <- 1 entier mois <- 1 entier annee <- 1901 fin structure { Calcul de la date suivant une date codee } { sous la forme jour mois annee en entier } { Version 1 } date fonction jourSuivant(-> date d) date dt dt.annee <- d.annee dt.mois <- d.mois dt.jour <- d.jour+1 si dt.jour > nombreJoursMois(d.mois,d.annee) alors dt.jour <- 1 dt.mois <- dt.mois+1 si dt.mois > 12 alors dt.mois <- 1 dt.annee <- dt.annee+1 fsi fsi retourner dt fin fonction { Version 2 } action jourSuivant(-> date d,date dt ->) dt.annee <- d.annee dt.mois <- d.mois dt.jour <- d.jour+1 si dt.jour > nombreJoursMois(d.mois,d.annee) alors dt.jour <- 1 dt.mois <- dt.mois+1 si dt.mois > 12 alors dt.mois <- 1 dt.annee <- dt.annee+1 fsi fsi fin action Exemple d'exécution
d) Ecrire un sous-algorithme de modification d'une date codée sous la forme jour-mois-année en nombres pour l'incrémenter de un jour.
jourDApres.lda structure date entier jour <- 1 entier mois <- 1 entier annee <- 1901 fin structure { Modification d'une date codee sous forme } { jour mois annee en entier pour passer } { au jour d'apres } action jourDApres(-> date d ->) d.jour <- d.jour+1 si d.jour > nombreJoursMois(d.mois,d.annee) alors d.jour <- 1 d.mois <- d.mois+1 si d.mois > 12 alors d.mois <- 1 d.annee <- d.annee+1 fsi fsi fin action Exemple d'exécution