Quelques raccourcis :
Vous trouverez ici quelques documents et quelques liens pouvant, je l'espère, vous être utiles.
Les documents qui vous sont fournis ici le sont pour vous rendre service.
Je travaille très fort sur chacun de mes cours. Veuillez ne pas vendre (ou donner) les documents que je vous offre ici à qui que ce soit sans mon consentement. Si des abus surviennent, je vais cesser de rendre ce matériel disponible à toutes et à tous.
Si ces documents vous rendent service, faites-le moi savoir. Mon adresse de courriel est disponible via la page où on trouve mon horaire.
Si vous êtes curieuses ou curieux de voir un vieil examen (celui de la cohorte 02!), pour voir le style de question que vous pouvez rencontrer, voir UdeS-COA--Controle-Final--Cohorte-02.pdf (mais ne vous basez pas sur les questions pour le contenu, qui évolue à chaque année)
![]() | Plan de cours (à venir incessamment) |
![]() | Document d'accompagnement au plan de cours |
Les quelques sections qui suivent réfèrent à ce que nous avons fait (ou allons faire) en classe cette session.
|
Séance |
Date |
Détail |
|---|---|---|
|
|
Au menu :
En vue de notre prochaine rencontre, je vous ai proposé de vous amuser avec le problème de la rédaction d'un jeu de Mastermind. |
|
|
|
Au menu :
Si vous souhaitez faire des exercices, dans les notes de cours :
Une variante du code du singleton simpliste utilisé ce matin va comme suit (voir https://wandbox.org/permlink/5HRCnprt4nhQDQEl pour une version exécutable) : Et voilà! Pour vous donner une idée de ce à quoi la matière d'aujourd'hui peut servir, imaginez ceci :
Comme vous pouvez le voir, afficher un monde (ici : les objets 3D vers lesquels pointent les éléments du vecteur v) et le nettoyer (ici, on suppose que les pointés peuvent être supprimés par delete, mais il y a des alternatives) devient tout simple quand on sait s'exprimer à l'intérieur des idiomes de notre langage. Autre exemple simple mais sympathique : supposons un jeu où il y a des monstres et où il faut périodiquement filtrer ceux qui sont morts. Supposons que Monstre soit à peu près comme suit : ... donc que Monstre soit une classe polymorphique telle que ce sont principalement ses dérivés que nous utilisons en pratique. Ainsi, une fonction qui filtre les monstres morts d'un vector<Monstre*> pourrait être : ... ou plus simplement encore : Essayez de programmer cette fonction sans recours aux algorithmes standards et aux λ. Vous constaterez sans doute que le problème n'est pas banal... |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Au menu : à venir |
|
|
JOUR XX mois XX h-XX h |
Chic examen plein d'amour |
|
|
« S15 » |
|
Semaine de finalisation et de présentation du projet, avec présentation (date et heure à venir) |
Ce qui suit vous est gracieusement offert dans le but de vous épargner une recopie pénible d'exemples et de tests proposés dans les notes de cours.
L'exercice proposé est celui de la construction d'un petit jeu de devinette
L'exercice proposé est celui de la construction d'un petit jeu de Mastermind
Les consignes des travaux pratiques en lien avec le cours sont ci-dessous.
De manière générale :
Date de remise : début de la séance S06.
Ce travail s'intègre aux travaux pratiques de vos autres cours de la session, et est à faire sur une base individuelle. Réfléchissez à l'application pertinente et justifiée par vous-même dans l'un ou l'autre de ces travaux pratiques :
Si vous éprouvez des difficultés à intégrer un élément technique précis, je suis ouvert à ce que vous proposiez une thématique technique équivalente. Dans le doute sur le caractère équivalent ou non de votre proposition, contactez-moi!
Notez que ce que vous proposerez doit se distinguer des exemples proposés par votre chic prof. Présentez chaque application en la mettant en contexte et en décrivant son fonctionnement, code à l'appui. Montrez clairement les éléments que vous intégrez à vos projets, et mettez en valeur la pertinence de vos choix. Le but de ce travail est de vous aider à progresser dans votre développement, pas de vous nuire.
Pour qu'on se comprenne bien, voici le genre de truc auquel je m'attends (adaptez à votre style personnel, évidemment), mais avec un exemple simpliste. Supposons que vous avez refactorisé une fonction écrite à l'ancienne pour profiter des algorithmes standards (notez que dans cet exemple, on a aussi une λ alors c'est un « deux pour un »!) :
Cher chic prof, dans notre projet, nous avons rapidement produit beaucoup de code pour s'apercevoir, en cours de route, qu'il était devenu difficile à entretenir. Je me suis penché sur quelques fonctions particulièrement « douloureuses » à mes yeux, et j'ai essayé de les retravailler pour que nous puissions mieux les comprendre et les faire évoluer.
En particulier, j'ai rencontré cette chose :
int trouver_plus_pres_de(Point pt, vector<Point> candidats) {
if (candidats.size() == 0) return -1; // personne
int reponse = 0; // optimiste
double plus_proche_dist = numeric_limits<double>::max(); // loin!
for(int i = 0; i < candidats.size(); ++i) {
if (pt != candidats[i] && pt - candidats[i] < plus_proche_dist) {
reponse = i;
plus_proche_dist = pt - candidats[i];
}
}
return reponse;
}C'est pas très joli, j'en conviens. En y regardant de plus près, on y voit :
Je me suis demandé si je serais capable de mettre en mots ce que la fonction fait, comme tu l'as suggéré en classe, et je me suis dit que le nom de la fonction faisait bien ce travail : cette fonction sert à trouver le Point dans candidats qui est le plus proche de pt (sans y être superposé). Je me suis dit alors que je pourrais y aller comme ceci :
Si candidats est vide
Retourner -1 // cas dénégéré
plus_proche ← trouver premier autre que pt dans candidats
Si plus_proche = pt
Retourner 0 // seul au monde
distance_plus_proche ← *plus_proche - pt
Tant que je n'ai pas épuisé les Points candidats
plus_proche ← trouver plus proche que plus_proche
distance_plus_proche ← *plus_proche - pt
Retourner distance(debut(candidats), plus_proche)Ce qui se traduit directement en code :
int trouver_plus_pres_de(const Point &pt, const vector<Point> &candidats) {
if (candidats.empty()) return -1; // cas dégénéré
auto plus_proche = find_if_not(next(begin(candidats)), end(candidats), pt);
if (plus_proche == end(candidats)) return 0; // seul au monde
auto distance_plus_proche = *plus_proche - pt;
for(plus_proche = find_if(plus_proche, end(candidats), [&](const Point &p) { return p != pt && pt - p < distance_plus_proche; });
plus_proche != end(candidats);
plus_proche = find_if(plus_proche, end(candidats), [&](const Point &p) { return p != pt && pt - p < distance_plus_proche; }))
distance_plus_proche = *plus_proche - pt
return distance(begin(candidats), plus_proche);
}C'était pas si mal, mais ce n'était pas encore le bonheur. Entre autres, il y avait un peu plus de code qu'avant, ce qui me rendait triste.
J'ai pris sur moi de retravailler ma solution. En nommant la λ, c'était déjà un peu mieux (mais fallait vraiment capturer par référence, sinon ça ne fonctionnait pas) :
int trouver_plus_pres_de(const Point &pt, const vector<Point> &candidats) {
if (candidats.empty()) return -1; // cas dégénéré
auto plus_proche = find_if_not(next(begin(candidats)), end(candidats), pt);
if (plus_proche == end(candidats)) return 0; // seul au monde
auto distance_plus_proche = *plus_proche - pt;
auto pred = [&](const Point &p) { return p != pt && pt - p < distance_plus_proche; };
for(plus_proche = find_if(plus_proche, end(candidats), pred);
plus_proche != end(candidats);
plus_proche = find_if(plus_proche, end(candidats), pred))
distance_plus_proche = *plus_proche - pt
return distance(begin(candidats), plus_proche);
}Cependant, j'en ai discuté avec mes collègues et nous nous sommes aperçus que ce dont nous avions vraiment besoin, c'était la distance la plus courte entre un Point candidat et pt. Nous nous donnions la peine de repérer une position alors que nous ne voulions qu'un minimum! J'ai donc réécrit le tout plus simplement :
double plus_courte_distance_de(const Point &pt, const vector<Point> &candidats) {
if (candidats.empty()) return -1.0; // cas dégénéré
auto cur = find_if_not(begin(candidats), end(candidats), [&pt](const Point &p) { return p != pt; });
if (cur == end(candidats)) return 0.0; // seul au monde
return accumulate(next(cur), end(candidats), *cur - pt, [&pt](double so_far, const Point &p) {
return pt == p? so_far : std::min(so_far, pt - p);
});
}... et c'est plus direct, plus clair et plus rapide (voir résultats des tests en annexe). Voilà!
Notez qu'il arrive régulièrement que des étudiant(e)s de ce cours arrivent au point où il leur faut livrer ce travail pratique et font le constat qu'ils n'ont pas encore commencé à appliquer des techniques et des concepts du cours, ayant (consciemment ou non) fait le « choix » de rester dans le confort de leurs habitudes. Ne vous faites pas prendre; prévoyez le coup en mettant le plus systématiquement possible en pratique ce que vous voyez dans le cours!
Date de remise : début de la séance S12 (en fait, quand vous aurez fini votre projet, car c'est la priorité)
Il se fait tard, vous souhaitez produire et conclure votre session, et je souhaite pouvoir savoir où vous en êtes sans toutefois vous surcharger. Voici ce que je vous propose :
L'idée est de produire une très brève autocritique de contribution individuelle et de design global qui puisse servir de rampe de lancement au projet de cet hiver. Autocritique ne signifie pas autoflagellation : personne n'est parfait et l'école est un lieu d'apprentissage.