Département d`informatique

publicité
Département d’informatique et de génie logiciel
Université Laval
Professeur : Clermont Dupuis
Bureau : 3976
IFT-21937 Introduction à l’algorithmique et à la programmation
Examen sur 35
Date : 19 octobre 2006
Aucune documentation permise.
Question # 1. (2 points)
(i)
Vous partez de la ville de Québec pour vous rendre à la ville de Montréal. Chaque
pas que vous faites vous permet de franchir la moitié de la distance qui vous reste
à parcourir pour atteindre la ville de Montréal.
Votre stratégie pour vous rendre à la ville de Montréal correspond-elle à un
algorithme ? Expliquez.
Non, car cette stratégie donne lieu à un nombre infini d’opérations élémentaires.
(ii)
Expliquez pourquoi une recette de cuisine ne correspond pas à un algorithme la
plupart du temps ?
Parce qu’un algorithme doit être une procédure non ambigüe. On retrouve souvent
dans une recette de cuisine des opérations qui laissent place à interprétation (par
ex., ajouter une à deux pincées de sel).
Question # 2. (2 points)
Afin de choisir l’algorithme le plus efficace pour résoudre un problème, nous pouvons
opter pour une approche théorique en effectuant une analyse en pire cas. Décrivez cette
approche théorique en pire cas et illustrez à l’aide d’un exemple concret.
Cette approche théorique consiste à calculer le nombre d’opérations élémentaires
nécessaires à l’algorithme pour résoudre le problème. En effectuant une analyse en pire
cas, il s’agit de calculer le # d’opérations élémentaires nécessaires à l’algorithme pour
résoudre le problème dans le pire cas (les données du problème où l’algorithme est le
plus coûteux).
Exemple : La recherche séquentielle d’un mot dans le dictionnaire en commençant notre
recherche à la première page du dictionnaire. La pire situation où l’algorithme
sera le moins performant intervient lorsque le mot recherché se trouve dans la
dernière page du dictionnaire.
Question # 3. (3 points)
Concevoir un algorithme (et non un programme) qui lit en entrée un entier positif n et
détermine si n est un nombre premier ou non.
1. Lire un entier positif n.
2. Pour chaque valeur de i entre 2 et n
2.1 Si le reste de la division de n par i est égale à 0 (i est facteur de n) alors
2.1.1 Écrire que le nombre n n’est pas premier.
2.1.2 L’algorithme prend fin.
3. Écrire que le nombre n est premier.
4. L’algorithme prend fin.
Question # 4. (1 point)
Qu’est-ce qu’un compilateur ?
C’est un programme informatique permettant de traduire un programme écrit dans un
langage de haut niveau tel que C ou C++ en langage d’assemblage plus près de la
machine.
Question # 5. (2 points)
Qu’entend-on par la méthode de raffinement successif pour concevoir un algorithme ?
Une première version de l'algorithme est obtenue où les étapes de cet algorithme ne sont
probablement pas assez détaillées pour que l’algorithme puisse être implanté. Chaque
étape doit donc être affinée en une suite d'étapes plus élémentaires, chacune étant
spécifiée d'une manière plus détaillée que dans la première version. Le processus de
raffinement se termine lorsque l’algorithme est décrit uniquement à partir d’opérations
élémentaires.
Question # 6. (2 points)
(i)
Donnez la représentation en base 2 du nombre 25 en base 10.
110012
(ii)
Donnez la valeur décimale du nombre 10101 en base 2.
16 + 4 + 1 = 21.
Question # 7. (2 points)
Étant donné les instructions suivantes :
2
char a = 3;
int b = 4;
float c;
cout << (c = (float) a / b);
quelles sont les conversions effectuées dans cette dernière instruction et quelle est la
donnée affichée ?
Le type de la variable a est convertie en float; a / b entraîne alors une conversion
implicite du type de la variable b en float. On obtient alors comme résultat de la division
réelle 0.75, un type float. Puisque c est de type float, c prend la valeur 0.75 sans
conversion.
char a=3;
int b = 4;
cout << (c = (float) a / b);
Ex. :
float c;
0.75
conversion automatique en float
conversion forcée en float
Question # 8. (2 points)
Étant donné les instructions suivantes :
int r = 1, b = 5; i = 3;
while (i > 0)
{
if (i%2 == 0)
{
b = b  b;
i = i / 2;
}
else
{
r = r *b;
i--;
}
}
que contiennent les variables r, b et i à chaque itération ?
r
b
i
1
5
5
125
5
5
25
25
3
2
1
0
3
À la sortie de la boucle, r contient la valeur de 53.
Question # 9. (1 point)
Construire la table de vérité de cette expression où p est une variable booléenne et
montrez que cette expression est toujours fausse :
p && !p
p
&&
!p
v
f
fv
f
f
vf
Question # 10. (1 point)
Dans la portion de programme suivante, dites pourquoi l’instruction d’affectation k = 5;
doit être déplacée ? À quel endroit devrait-elle être placée sans changer le résultat affiché.
int k;
for (int i = 1; i <= 10; i++)
{
k = 5;
cout << i + k;
}
Puisque k ne change pas de valeur au cours de chaque itération de la boucle, on devrait
exécuter l’instruction d’affectation une seule fois avant d’exécuter la boucle for.
Question # 11. (2 points)
Dans la portion de programme suivante, on retrouve une erreur de logique classique :
int k = 1;
while (k <= 10)
{
for (int i = 1; i <= k; i++) cout << '*';
cout << endl;
}
À l’affichage, on compte obtenir le résultat suivant :
*
**
***
****
*****
4
******
*******
********
*********
**********
Indiquez l’erreur et comment la corriger ?
Dans la boucle while, la variable k n’est pas incrémentée de sorte que nous avons une
boucle infinie. Pour corriger la situation, ajouter à la fin de chaque itération l’instruction
k = k + 1;
Question # 12. (5 points)
Écrire un programme qui lit en entrée les valeurs entières A, B et C représentant
respectivement la longueur de chaque côté d’un triangle. Supposons que A représente la
longueur du côté le plus long, B et C la longueur des deux autres côtés, alors il s’agit
d’afficher l’un ou l’autre des messages de la colonne de droite :
A≥ B+C
A2 = B2 + C2
A2 < B2 + C2
A2 > B2 + C2




Ce n’est pas un triangle.
C’est un triangle rectangle.
C’est un triangle aigu.
C’est un triangle obtu.
#include <iostream.h>
void main()
{
int A, B, C;
int Diff;
cout
<< "Entrez la longueur des 3 cotes d'un triangle"
<< " en commencant par le plus long : " << endl;
cin >> A >> B >> C;
Diff = A * A - B * B - C * C;
if (A >= B + C) cout << "Ce n'est pas un triangle." << endl;
else
{
if (Diff == 0)
cout << "C'est un triangle rectangle." << endl;
else if(Diff < 0) cout << "C'est un triangle aigu." << endl;
else
cout << "C'est un triangle obtu." << endl;
}
}
5
Question # 13. (5 points)
Écrire un programme qui lit en entrée N entiers, détermine le plus grand entier parmi les
N entiers et, finalement, affiche le maximum obtenu.
Note : On suppose que N = 10 dans ce programme.
#include <iostream.h>
void main()
{
const int nombre_d_entiers = 10;
int
entier,
max,
i = 1;
// le # d’entiers à lire.
// un entier à lire.
// le maximum parmi les entiers.
// indice de boucle.
while (i <= nombre_d_entiers)
{
cout << "Entrez la " << i << " ieme valeur : ";
cin >> entier;
if (i == 1) max = entier;
else if (max < entier) max = entier;
i = i + 1;
}
cout
<< "Le plus grand entier est : "
<< max << "." << endl
}
Question # 14. (5 points)
6
Une année est bissextile tous les 400 ans; les siècles ne sont pas bissextiles et
une année sur 4 est bissextile
1. Lire une année n.
2. Si n possède comme facteur 400 alors
2.1 Écrire que n est une année bissextile.
2.2 L’algorithme prend fin.
3. Si n possède comme facteur 100 alors
3.1 Écrire que n n’est pas une année bissextile.
3.2 L’algorithme prend fin.
4. Si n possède comme facteur 4
alors écrire que n est une année bissextile.
sinon écrire que n n’est pas une année bissextile.
5. L’algorithme prend fin.
Écrire un programme en C++ qui traduit l’algorithme précédent.
#include <iostream.h>
int main()
{
int annee;
cout << "Entrez l'annee desiree : ";
cin >> annee;
if ((annee % 400) == 0)
{
cout << "oui." << endl;
return 0;
}
if ((annee % 100) == 0)
{
cout << "non." << endl;
return 0;
}
if ((annee % 4) == 0) cout << "oui." << endl;
else cout << "non." << endl;
return 0;
}
°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
7
Téléchargement