[LOGO]

Fonctions et tableaux


Comme pour les TPs précédents, on vous demande de créer un répertoire tp6 qui contiendra les exercices de cette feuille de TP et de faire un compte rendu de TP en HTML.

Exercice 1 : Retour vers le futur — Seuls ceux qui passent les tests compteront !

Cet exercice est une reprise de l'exercice 3 du TP 5. Si vous aviez déjà fait cet exercice, vous pouvez passer directement à l'exercice suivant.
Cet exercice est l'occasion d'écrire des fonctions qui prennent d'autres fonctions en argument, et/ou qui renvoient une fonction. Comme d'habitude, on n'oubliera pas de tester chacune des fonctions que l'on aura écrites.
  1. Recopiez la page Web exo1.html dans votre répertoire tp6.
  2. Écrire une fonction estPair qui, étant donné un entier k, renvoie true si k est pair, et false sinon.
  3. Écrire une fonction estCarré qui, étant donné un entier k, renvoie true si k est un carré parfait, et false sinon.
  4. Écrire une fonction comptePairs qui, étant donné un entier n strictement positif, énumère les entiers de 1 à n, compte combien d'entre eux sont pairs, et renvoie le résultat de son décompte.
  5. Écrire une fonction compteCarrés qui, étant donné un entier n strictement positif, énumère les entiers de 1 à n, compte combien d'entre eux sont des carrés parfaits, et renvoie le résultat de son décompte.
Ci-dessus, on a écrit deux fois la même chose, à ceci près qu'on a décompté les entiers pairs dans notre première fonction, et les carrés parfaits dans notre deuxième fonction. Comme la duplication de code est une erreur critique en programmation, il faut revoir les choses.
On va donc réécrire de manière plus professionnelle les fonctions comptePairs et compteCarrés, en créant une fonction compte qui prend un argument test et dont le comportement sera le suivant :
  1. Comment écrire la fonction compteCarrés2, qui fait la même chose que compteCarrés, à partir des fonctions test et estCarré ? Cette réécriture est censée prendre une seule ligne de code.
  2. Écrire la fonction compte.
    Bien vérifier que les fonctions comptePairs2 et compteCarrés2 réécrites à partir de la fonction compte se comportent comme les fonctions comptePairs et compteCarrés.
  3. Écrire, en une seule ligne de code, une fonction compte1mod3 qui, étant donné un entier n strictement positif, énumère les entiers de 1 à n, compte combien d'entre eux sont congrus à 1 modulo 3, et renvoie le résultat de son décompte.

Exercice 2 : Tableaux

Manipulations simples de tableau

  1. Recopiez la page Web exo2.html dans votre répertoire tp6.
    Expliquez ce que fait le code sans pour autant regarder le code de graph.js.
    Note : pour tester, vous devez récupérer aussi le fichier graph.js et le placer correctement par rapport au fichier exo2.html que vous venez de récupérer (Une piste pour le trouver : regarder la source…)
  2. La suite de cet exercice consiste à compléter chaque question en écrivant un code à l'endroit des 'TODO'.
    On cherche à écrire une fonction addThree qui prend en paramètre un tableau et retourne un nouveau tableau qui contient le même nombre de cases que le tableau pris en paramètre et dont les valeurs des cases est la valeur de la case de même index du tableau pris en paramètre augmentée de trois.
    Par exemple, si le tableau initial contient [11, 21, 5, -13, 2, 12, 19, 5], alors le résultat de l'appel à addThree doit être un nouveau tableau avec les valeurs [14, 24, 8, -10, 5, 15, 22, 8].
    Si cela vous aide, vous pouvez dans un premier temps écrire l'algorithme en pseudo-code, puis dans un deuxième temps, transformez le pseudo-code en JavaScript.
    Attention ! Votre fonction ne doit pas modifier le tableau d'origine.
  3. En fait, le code que l'on a écrit n'est pas très générique : si l'on doit ajouter 4 à chaque case ou alors multiplier la valeur des cases par 2, il faut dupliquer le code avec un copier/coller et changer l'opération à effectuer.
    Comme on n'est pas des barbares, on se dit que l'on pourrait réutiliser la même fonction pour tous ces cas. On va pour cela créer une fonction intermédiaire.
    Donc dans un premier temps, écrivez une fonction applyForEachElement qui prend deux arguments (un tableau et une fonction) et qui, pour chaque élément du tableau, appelle la fonction en lui donnant l'élement en guise de paramètre.
    Une fois que applyForEachElement marche, écrivez une nouvelle version de addThree, addThree2 qui va utiliser applyForEachElement, vérifiez que le résultat est identique.
Les questions qui suivent utilisent les fonctions sur les tableaux que vous avez vues ce lundi en cous magistral. Comme c'est tout récent, elles sont donc facultatives.
  1. Il y a toutes les chances que votre fonction applyForEachElement contienne une boucle for. Cependant, on peut éviter d'écrire cette boucle explicitement, en utilisant la méthode forEach sur un tableau : écrire la fonction applyForEachElement2 pour utiliser la méthode forEach, puis l'utiliser pour écrire une nouvelle version de addThree, nommée addThree3.
  2. Que fait la méthode map si on l'appelle sur un tableau ?
    Comment peut-on l'utiliser pour écrire addThree ?
    Écrivez addThree en utilisant la méthode map et vérifiez que l'on obtient le même résultat que précédemment.
  3. On souhaite afficher les valeurs du tableau trié en utilisant la méthode sort sur un tableau.
    Rappelez en quoi la méthode sort est différente des méthodes map et filter.
    Écrivez la fonction sortedArray qui renvoie un nouveau tableau avec les valeurs triées (Attention ! Le tableau pris en paramètre ne doit pas être modifié).
  4. On veut afficher les valeurs du tableau seulement si celles-ci sont positives ou nulles.
    Sachant que l'on peut utiliser la méthode filter sur un tableau, écrivez la fonction positiveArray qui renvoie un tableau ne contenant que les valeurs positives ou nulles du tableau pris en paramètre.

Exercice 3 : MinMax, génération aléatoire et calcul rapide

On cherche à calculer le minimum et le maximum d'un tableau sans parcourir le tableau plusieurs fois.
Avant de commencer, recopiez la page Web exo3.html dans votre répertoire tp6 .

  1. On cherche à écrire une fonction minmax qui prend en paramètre un tableau, calcule le minimum et le maximum de ce tableau et renvoie les deux valeurs sous forme d'un nouveau tableau à 2 cases dont la première case est le minimum et la seconde case est le maximum.
    Pour des questions d'efficacité, on veut que le calcul du minimum et du maximum soit fait lors du même parcours du tableau.
    Écrivez, dans un premier temps, l'algorithme que vous allez implanter en pseudo-code, puis écrivez le code JavaScript correspondant.
    Note : il existe les fonctions Math.min et Math.max.
  2. Au lieu d'écrire la boucle à la main, on peut vouloir directement utiliser l'opérateur spread (…) pour calculer le minimum et le maximum du tableu.
    Écrivez le code de minmax2 qui utilise cet opérateur. Si l'on utilise cette fonction, combien de fois aura-t-on parcouru le tableau ? Cela satisfait-il les contraintes posées en début d'exercice ?
On peut améliorer le code obtenu à plusieurs endroits.
Au lieu de tester avec un tableau écrit « en dur », tirer aléatoirement un tableau permettrait de tester avec davantage de tableaux différents.
De plus, l'algorithme minmax écrit précédemment n'est pas le plus efficace. Il existe une version qui fait moins de comparaisons (et qui est bien sûr plus compliquée à écrire).
  1. On souhaite pouvoir mélanger les cases d'un tableau dans le but de tester plus de combinaisons.
    L'idée de l'algorithme de mélange est la suivante : pour chaque case i, on tire un nombre aléatoire entre i et n - 1 (n étant le nombre de cases du tableau) et l'on va permuter (échanger si vous préférez) la case courante avec la case à l'index du nombre que l'on vient de tirer aléatoirement.
    Si l'on fait cela pour toutes les cases, le tableau sera mélangé (et on peut même s'offrir la joie de démontrer que ce tableau est bien échantillonné uniformément au hasard parmi tous les tableaux possibles).
    Écrivez dans un premier temps une fonction swap qui permet d'échanger deux cases du tableau.
    Puis écrivez la fonction randomArray qui mélange les valeurs du tableau pris en paramètre.
    Note : tirer un nombre aléatoire entre 0 (inclus) et n (exclu) en JavaScript se fait avec la fonction suivante :
    const random = n => Math.floor(n * Math.random());
  2. Il est possible de diminuer le nombre de tests fait par la fonction minmax. En effet, si au lieu de faire évoluer le min et le max pour chaque case du tableau, on commence par lire deux valeurs de cases consécutives, regarder quelle est la plus grande puis la comparer avec le max, dans ce cas, la valeur la plus petite ne doit être comparée qu'avec le min donc chaque case n'a pas besoin d'être comparée et avec le max et avec le min.
    Écrivez dans un premier temps l'algorithme en pseudo-code.
    Note : pour éviter de dupliquer le code, on peut écrire le code si une valeur est plus grande que l'autre et dans l'autre cas, permuter les valeurs (attention, les valeurs, pas les cases du tableau) pour se retrouver dans le même cas.
    Vérifiez que votre algo fonctionne que le nombre de cases soit pair ou impair.
    Enfin, écrivez la fonction minmax3.