annales
annales
annales
Annals of examinations
(In French until 2020). Corrections are available on the course web page (http://
imagine.enpc.fr/~monasse/Info/).
The following functions and constant from #include <cmath> will be used: sqrt,
cos, sin, exp, log and M_PI (π). Consistently labeling methods as const when ap-
propriate will be appreciated.
Cosine Gaussian
Figure 1: Some usual functions (black) and their power spectrum (red).
1
More fun with the discrete Fourier transform will be illustrated in the course “Algorithmics and
Data Structures”, along with a fast algorithm to compute it.
1.2 Complex numbers
2. Define two constructors for the class, the first one taking a single float for the
real part (representing a real number), the second one taking two for real and
imaginary parts.
3. Define the operators for addition and subtraction of two complexes outside the
class.
4. Define the method bar returning the conjugate z̄ of its complex argument z.
5. Define the methods modulus and modulus2 of class complex. The latter is |z|2 =
z z̄ ∈ R and the former its square root.
6. Define the operators for multiplication and division of two complexes outside the
class.3 For the latter, remember that 1/z = z̄/|z|2 . The real 1/|z|2 can be computed
and the formula implemented as a multiplication of three terms.
8. Define the function exp computing the exponential of a complex number. Re-
member that eiθ = cos θ + i sin θ.
9. Following the model of Section 12.2.3 of the lecture notes, define operator<< so
that we can write cout << z. Use compact display, see next question.
10. In a function test_4ops(), called from main(), define complex constants zero,
one and i and make it print the following complex numbers:
0 1 i -i 1+i 1-i 2+3i
Notice it is the compact format we require, the following represent the same with
a bad format:
0+0i 1+0i +1i -1i 1+1i 1-1i 23i
(the last one a bug because float im=3; cout<<im; does not display the +).
2
1.3 Signal
1.3 Signal
12. In a new separate file, define a class Signal storing an array of float numbers
whose number of elements is not known in advance. Two fields n and nmax,
always with n ≤nmax, control the array: nmax is the current size of the allocated
array and n the actual numbers of elements used.
13. Write a constructor with no argument, the signal is initially empty with nmax=0
and the array not allocated.
15. Write the copy constructor. Bonus: in which question and why is it crucial to have
the copy constructor defined? (answer as comments in code).
16. Write a method size returning the actual number of elements and operator[]
for element access, the latter checking with assert that the index makes sense.
17. Write a method add appending its float argument to the signal. If n =nmax we
must (re)allocate an array: if n = 0 we put nmax= 1, otherwise we double nmax.
18. Write a method bounds computing the minimum and maximum values of the
signal.
Do not recompute the complex exponential for each term of the sum, use the
recurrence relation e−2i(j+1)kπ/n = e−2ikπ/n e−2ijkπ/n (geometric sequence).
20. Write a method modFourier returning a new signal with the same length and
with coefficients log(1 + |fˆ[k]|), 0 ≤ k < n (the power spectrum).
21. The second half of the Fourier coefficients should rather be considered as nega-
tive frequencies, so write a method shift that swaps the two halves of the signal
(index k = 0 is at the middle, −1 at its left, +1 at its right, etc).
22. The equation for the affine function y = ax+b passing through (x1 , y1 ) and (x2 , y2 )
has coefficients a = (y1 − y2 )/(x1 − x2 ) and b = (x1 y2 − x2 y1 )/(x1 − x2 ). Write the
function computing a and b (if x1 = x2 take a = 0, b = (y1 + y2 )/2).
23. Write a function draw taking a signal S, coefficients ax , bx , ay , by and a color, and
drawing a polygonal line joining points (ax k + bx , ay S[k] + by ).
3
1.4 Display power spectra
24. Write another function draw taking a signal S and displaying the graph of S in
the left half of a window of size w × h = 512 × 128 and its power spectrum in
the right half. Each graph is displayed with a scale adapted to the bounds of the
signal and letting margin= 16 pixels of white padding around. A blue line at
the middle separates the graphs.
25. Write and call from main a function noise generating a signal with random val-
ues in [0, 1] and displaying it and its power spectrum. The number of samples is
a constant nsamples= w/2.
26. Same with function heaviside: the signal is 1 if t < c = n/4, 0 otherwise.
28. Same with function cosine: f [k] = cos(2if kπ/n) with f = 10 an integer.
30. Modify the function draw of Question 24 so that it ends with waiting for a user
clicks and returns false in case of right click. Otherwise, the pointer abscissa
converted to signal coordinates X = (x − bx )/ax is computed.
31. Modify the different signals so that the parameters are chosen interactively by
the user until a right click: c = X, r = f = σ = |X − n/2|.
4
2. Midterm examination on machine 2022
Note that P (0) = P0 and P (1) = P3 but P1 and P2 are not on the curve in general. Our
program explores the various shapes the curve can take. Without loss of generality, we
will assume P0 = (0, 0) and P3 = (1, 0).
3. Define the operators for multiplication and division by a float . For multiplica-
tion, define the two operators: float *point and point* float .
5
2.3 Bézier curve
4. Define a function affine taking a point and applying the similarity P → a∗P +S
with parameters a the zoom factor and S a point (shift). It will be used to map
standard coordinates of the curve to pixel coordinates for drawing.
5. Define a function rotate that rotates a point P around a center C with an angle
α expressed in degrees. Functions cos and sin from #include <cmath> take their
argument in radians.
7. Write a function initBezier that returns a new curve with P1 = (1/3, 0) and
P2 = (2/3, 0).
8. To draw the curve, we will zoom and shift the coordinates for display. The win-
dow will be square with dim×dim pixels, point P0 will be displayed at (dim/3,dim/2)
and P3 at (2dim/3,dim/2). Values of s will be discretized uniformly at npoints=
100 values. Define the adequate constants, dim= 512.
9. The function draw takes a curve and displays it: draw a blue line from P (s) to
P (s + δs) (use affine to apply the transform) with δs = 1/npoints.
10. Add in the previous function the display of the 4 points (red for extremities, green
for P1 and P2 ), disks of radius= 3 pixels.
11. Make the main function display an initial Bezier curve and wait for a click to
continue.
2.4 Animation
12. Write a function animate in the main file that applies 100 iterations of rotation
around P0 of P1 = (3/4, 0) and of P2 = (2/3, 0) around P3 . At iteration i, P1 rotates
of i ∗ 10◦ and P2 of i ∗ 3◦ . After each display, a small pause is observed. At the
end, the function should wait a point click.
13. Enrich the function draw by linking the control points by lines in gray color of
intensity 200. This should be done at the beginning of the function, so that it does
not overlap with the rest.
6
2.5 User interaction
15. Write a function interactive. It displays an initial Bézier curve and loops
undefinitely until selectPoint returns with a right click. Inside the loop, it lets
the user move the selected controlled point and displays interactively the curve.
The function track (see figure) is used to detect a mouse motion or the mouse
button release. In case of motion, the shift from the previous position in pixels is
applied to the control point. Be careful that the scale of display is not the same as
the point coordinates.
16. Bonus: (i) Move the interactive control in a separate program (within the same
project CMakeLists.txt), and (ii) create a library for the common functions of the
two programs.
7
3. Final examination on machine 2021
i n t keyboard ( ) {
Event e ;
do {
wDino h hFloor getEvent ( 0 , e ) ;
i f ( e . type == EVT_KEY_ON)
hDino ball motion at speedBall r e t u r n e . key ;
xDino altitude
hBall wBrick } while ( e . type ! =EVT_NONE ) ;
return 0;
floor motion
}
Figure 2: Blue jumping dinosaur and red balls. Altitude is variable (when the dinosaur
jumps), computed question 4. The function keyboard returns the pressed key code
(without waiting), 0 if none. You can copy-paste it from Practical#8.
2. Write a class Dino and its constructor. It only needs an integer t storing the time
of the last jump start. A jump lasts for a constant time tJump=20 and reaches a
height hJump=3*hDino (yes, the dinosaur is heavy but is a high jumper!). Ini-
tially, the dinosaur is not jumping, so we put its t as sufficiently negative.
3. Method jump registers that a jump starts. Method jumping indicates if the jump
is still in process.
8
3.3 Life becomes harder with moving balls
4. Method altitude computes the altitude above the floor (0 if not jumping). Ac-
cording to Newton’s gravitation law, it has a parabolic evolution given by equa-
tion
2 !
t0 − t
h = hJump ∗ 1 − 1 − 2 . (3)
tJump
5. In a separate file, define a class Recorder. It has a field of type Dino. First this
class will be used to play the game, the recording part will be coded in Section 3.4.
6. Method Recorder::display clears the window and draws the dinosaur at the
current time.
7. Method Recorder::action calls the function keyboard: if the space bar key
is pressed, the dinosaur is set to start jumping but only if the last jump has fin-
ished.
8. In the main, let the user make the dino jump on demand.
10. A ball has diameter hBall=3/4 hDino and will be moving with a constant speed
speedBall=8 pixels per time increment. It stores a time and abscissa for an initial
position. Write class Ball in dino.h and a constructor, initially at abscissa 1000
for time 0.
12. Ball::center returns the abscissa of its center at current time. It is based on
initial position and speed, moving to the left (toward the poor dino).
13. Ball::reInit is used to recycle a ball that was dodged by the jumping dino
if it went out of screen: it restarts at abscissa xBase (a method parameter) plus
a random gap between one and three times tJump*speedBall pixels, but it must
appear to the right, so that the result is set to at least w (the window width). The
function returns true if recycling took place.
14. Add an array of nBalls=3 balls (nBalls is a constant) in class Recorder. In the
constructor of the class, the ball are regularly spaced from abscissa w with a space
of tJump*speedBall pixels.
15. Insert the display of balls in Recorder::display and call reInit on all balls
in method action. The parameter xBase of reInit is the position of preceding
ball.
9
3.4 Recorder replay
16. In the main, let the user play the game with a span of 20 milliseconds for each
time increment.
17. Add a method Dino::crash taking a ball and indicating whether the ball inter-
sects the rectangle of the dinosaur. The squared distance to the ball center can be
computed
with h the altitude of the dino and c the abscissa of the ball center.
18. Add method Recorder::crash indicating if the dino crashes with one of the
balls. Insert the crash test in the game, letting it finish when it happens.
19. Add a structure Action, a triplet (t, x, i) with t the time, x the abscissa and i the
ball number. An action is either a dino jump start (then x and i are set negative)
or a ball reinitialization.
20. The recorder will store all actions during the game. Insert a dynamic array
actions in Recorder reserving initially the space for one action. Modify con-
structor and destructor accordingly. The management of the array follows this
principle: nmax actions are initially allocated, but n = 0, the actual number of
stored actions.
23. Write Recorder::set taking a time and resetting the game at this time: find
the preceding stored jump in recorded actions, and for each ball the preceding
reinitialization.
24. When the game is finished, let the user visualize it back and forth by arrow keys.
10
4. Midterm examination on machine 2021
A variant of the
queens game.
11
4.3 Human player
3. Define a function init that puts the board in an alternance of black and white
cases.
4. Define functions draw and drawCase, respectively for the whole board and for
an individual case. Leave a one pixel wide space between adjacent cases.
7. Define the function centerCase that returns the pixel coordinates of the center
of the case at given row and column.
8. Write a function isFree that indicates whether a case at given row and column
is threatened by a queen of not (white and black indicate free cases, any other
color means it is not free).
10. Each queen is associated to a color. Write an array of n= 8 fixed colors (excluding
black and white).
11. Write a function forbid that takes a board and a case to paint the free cases
threatened by a queen placed there in the fixed color given by the column of the
queen. Instead of writing 8 loops, use an auxiliary function taking a position and
a direction vector (dx, dy) ∈ {−1, 0, 1} × {−1, 0, 1} \ {(0, 0)}.
12. Using the previous functions, in a function play inside the file containing the
main function, present an empty board to the player, let her click cases until no
more free cases are left. After each click on a free case, the board is repainted to
show the threatened case and the queen represented by a black disk.
13. Make the program write the score of the player (number of queens). It may be in
a console instead of the graphical window if you do not know how to do it.
12
4.4 Machine player
14. Write a structure tab storing an array of n integers. We will use some arrays with
fewer than n elements, but we will use a variable to store the actual number of
elements.
15. The function permute takes two such structures t and u and the actual number
of elements in t (if t has k elements, u has n − k) to generate all permutations.
16. For each permutation, a function check is called, which builds the correspond-
ing board and verifies if it is a winning configuration.
17. In that case, the filled board is shown and a message bragging about the result is
displayed. A mouse click is expected to continue searching for more configura-
tions.
13
5. Examen final sur machine 2020: énoncé
Figure 3: Les 8 pièces du jeu 10 × 10, composées d’au maximum 3 × 3 cases (cases
blanches non occupées par la pièce), chacune avec sa couleur. À droite, le jeu en cours
de partie. Une colonne remplie du plateau 10 × 10 a été détruite, d’où un score affiché
de 10 points. Le voyant rouge en haut indique que la pièce courante (un L orange),
située au centre, ne peut être déposée là car elle recouvre au moins une case occupée.
Le joueur doit la déplacer à un emplacement libre avant de la déposer.
5.2 Pièces
1. On laisse de chaque côté marge= 10 pixels avec le bord de la fenêtre, sauf en
haut avec margeScore= 50 pixels. On a une grille carrée de size= 10 cases de
côté et chaque case occupe z × z pixels avec z = 50. Ouvrir une fenêtre de taille
correcte pouvant afficher tout cela.
14
5.3 Plateau
3. Dans un fichier séparé, créer une classe Piece, composée de jusqu’à 3 × 3 cases
(un booléen indique si la case est remplie), une couleur et une position (x, y) de
la case centrale dans la grille.
7. Tester cette classe dans une fonction test_deplacement: les touches flèches
du clavier déplacent une pièce d’une case dans la direction indiquée (on ne véri-
fie pas si on sort de la grille), la touche “Entrée” termine la fonction. Utiliser
la fonction getKey d’Imagine++ qui renvoie le code de la touche appuyée par
l’utilisateur.
5.3 Plateau
10. Écrire sa méthode dessine. Les méthodes qui suivent prennent une pièce en
paramètre, que nous appelons p.
12. La méthode verifie indique si p n’occupe que des cases libres (blanches).
14. La méthode absorbe “fige” p en copiant sa couleur dans les cases du plateau
qu’elle occupe.
15. La fonction jeu est une première version qui affiche une nouvelle pièce, laisse le
joueur la déplacer avec les flèches du clavier, la fige (si l’emplacement est libre)
lors de l’appui sur la touche “Entrée” et passe à la pièce suivante. Le jeu s’arrête
lorsque la nouvelle pièce n’a aucun emplacement libre possible.
15
5.4 Jeu final
18. Tenir le compte et afficher le score (nombre de cases détruites) dans le jeu.
19. Indiquer par un disque vert ou rouge si l’emplacement courant de la pièce est
libre ou pas.
16
6. Examen partiel sur machine 2020: énoncé
17
6.3 Effets miroir
2. Écrire une fonction voisinh qui prend un bloc en argument et renvoie celui juste
à sa droite.
4. Programmer un operator<= qui indique si son argument gauche est inclus dans
son argument droite.
5. Écrire une fonction copie qui prend une image et un bloc pour renvoyer la sous-
image correspondante.
6. Écrire une fonction colle qui prend une image à la fois source et destination,
une image (plus petite) à coller et la position (x, y) du coin haut-gauche de col-
lage.
7. Écrire une fonction translate qui prend une image à la fois source et destina-
tion, un bloc et le vecteur de déplacement (dx, dy) indiquant où dupliquer ce bloc
de l’image (on peut supposer que les zones source et destination ne se recouvrent
pas).
8. Sécuriser copie et colle par des assert vérifiant qu’il n’y a pas de déborde-
ment.
10. Écrire une fonction miroirh qui prend une image et un bloc et échange les deux
moitiés côte à côte (utiliser le copier-coller défini ci-dessus).
11. Écrire une fonction miroirh prenant seulement une image et appelant de façon
répétée la précédente: on échange les deux moitiés (on présente le résultat), puis
les moitiés de chacune (on présente le résultat) et ainsi de suite jusqu’à obtenir
l’image initiale inversée horizontalement. Faire une deuxième itération pour
retrouver l’image originale. Pour les boucles, utiliser voisinh et operator<=
des blocs.
13. Définir un miroir mixte (horizontal/vertical, fonction miroirhv) qui échange les
deux moitiés horizontales (présente le résultat), puis chacune des moitiés verti-
calement (présente le resultat), puis chacun des blocs à nouveau horizontalement
et ainsi de suite. On obtient enfin l’image tournée de 180◦ . Itérer une deuxième
fois pour retrouver l’image initiale. Attention, on a besoin dans ce cas de deux
boucles imbriquées pour appliquer l’échange de moitiés sur tous les blocs.
18
6.4 Rotation
6.4 Rotation
14. Définir une fonction tourne prenant une image et un bloc, séparant le bloc en
quatre quarts et les faisant tourner. On pourra utiliser le principe que pour passer
de la liste (a, b, c, d) à (b, c, d, a), on peut faire: tmp=a; a=b; b=c; c=d; d=tmp;
15. La fonction tourne prenant simplement une image fait touner les quatre quarts,
puis chacun des quatres quarts de ces derniers, et ainsi de suite jusqu’à obtenir
l’image tournée de 90◦ . Itérer quatre fois pour retrouver l’image initiale.
6.5 Bonus
16. Les fonctions tourne et miroirhv requièrent que les images soient carrées de
taille 2n (c’est le cas de l’image Lena fournie, 512 × 512). Pour une image autre,
extraire la plus grande sous-image centrée vérifiant ces conditions.
18. Pour les ambitieux: plutôt qu’appliquer les permutations élémentaires brutale-
ment, on peut les faire de façon progressive en faisant les translations par étapes
(translation de n pixels en n translations de 1 pixel) pour un effet plus fluide. Le
plus simple est de garder l’image avant translation, d’en faire une copie, copier
les blocs dans l’image initiale pour coller dans la copie. Une fois toutes les trans-
lations effectuées, on peut remplacer l’image initiale par la copie finale.
19