JS Warmup

Voici quelques exercices que je donne à mes étudiant.e.s de deuxième année afin qu’ils ne perdent pas la main sur JS.

EXERCICE 1

Etant donnés les tableaux suivants :

const array = [1, 12, 3, 67, 1, 23, 0, 87];
const array2 = [1, 1, 2, 3, 4, 5];

const array3 = [0];
const array4 = ['never gonna', 'give you', 'up'];
const array5 = ['never gonna', 'let you', 'down'];

Ecrivez une fonction verifSortAsc qui prend en paramètre un tableau et vérifie qu’il est bien trié dans l’ordre ascendant. La fonction devra retourner true si c’est le cas, false sinon.

Exemples :

verifSortAsc(array) // false
verifSortAsc(array2) // true

Correction :

function verifSortAsc(t) {
  let res = true;
  // Vu que l'on compare t[i] à t[i+1], il faut arrêter la boucle à t.length - 1,
  // sinon on va pointer dans le vide au dernier tour de boucle.
  for (let i = 0, l = t.length - 1; i < l && res; i++) {
    res = t[i] <= t[i+1]
  }
  return res;
  
  // sinon en une ligne
  // return t.every((value, i, arr) => value <= (arr[i + 1] ?? value));
}

EXERCICE 2

Toujours avec ces cinq tableaux :

const array = [1, 12, 3, 67, 1, 23, 0, 87];
const array2 = [1, 1, 2, 3, 4, 5];

const array3 = [0];
const array4 = ['never gonna', 'give you', 'up'];
const array5 = ['never gonna', 'let you', 'down'];

Ecrivez une fonction verifSort qui prend en paramètre un tableau ainsi qu’un booléen asc. Si asc est true, on vérifie que le tableau passé en paramètre est trié par ordre ascendant, sinon par ordre descendant. Faites en sorte que si l’on ne passe pas de deuxième paramètre, le critère de vérification soit ascendant par défaut.

Exemples :

verifSort(array, true) // => doit retourner "false"
verifSort(array3) // => doit retourner "true"
verifSort(array2, true) // => doit retourner "true"
verifSort(array3, false) // => doit retourner "true"
verifSort(array5, false) // => doit retourner "true"

Correction :

function verifSort(t, asc = true) { // utilisation d'un "default parameter"
  let res = true; // par défaut on va dire que le tableau est bien ordonné
  
  // on boucle tant que l'on n'a pas atteint t.length - 1 ET que "res" vaut true
  for (let i = 0, l = t.length - 1; i < l && res; i++) {
    // à chaque tour de boucle, on revalorise "res".
    res = asc ? t[i] <= t[i+1] : t[i] >= t[i+1]; // si "asc", on teste par ordre croissant, sinon décroissant
  }
  // on retourne la valeur de res
  return res;
}

EXERCICE 3

3-a

Ecrivez une fonction reverseWord qui prend une chaîne de caractères en paramètre et qui retourne la chaîne de caractères inversée.

Exemple :

reverseWord("Hello World!") // => doit retourner "!dlroW olleH"

Correction :

function reverseWord(word) {
  // cet enchaînement de fonctions peut vous sauver la vie en entretien technique
  return word.split('').reverse().join('');
}

3-b

Ecrivez une fonction “reverseArray” qui prend en paramètre un tableau et qui retourne ledit tableau inversé. Exemple :

reverseArray(["Hello", "World!"]) // => doit retourner ["World!", "Hello"]

Correction :

function reverseArray(arr) {
  return arr.reverse();
  // pour les plus courageux et les plus courageuses
  // on pouvait faire comme ceci :
  // return arr.map((val, i, t) => t[t.length - 1 - i])
  // ou encore
  // const res = [];
  // for (let i = arr.length - 1; i >= 0; i--) {
  //   res.push(arr[i]);
  // }
  // return res;
}

3-c

Ecrivez une fonction “reverseWords” qui prend en paramètre un nombre indéfini de paramètres étant des chaînes de caractères (et non pas un tableau de chaînes de caractères) et qui retourne, cette fois-ci, un tableau contenant chaque mot inversé.

Exemple :

reverseWords("Hello", "World!") // => doit retourner ["olleH", "!dlroW"]

Correction :

// les points de suspension, on appelle cela le "rest parameters"
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters
function reverseWords(...words) {
  // ça peut s'utiliser ensuite comme un tableau
  return words.map(reverseWord);
}

3-d

À l’aide des trois fonctions écrites précédemment, écrivez une fonction qui prend en paramètre le tableau suivant et retourne ledit tableau inversé, de même que tous les mots qu’il contient.

const words = [
    'nwod uoy tel', 'annog reven',
    'pu uoy evig', 'annog reveN'
]

Correction :

function reverseAll(arr) {
  // Du coup il suffit ici de composer les fonctions
  // Vous remarquerez que "reverseAll" prend un tableau en paramètre
  // mais "reverseWords" ne prend pas de tableau.
  // Le fait d'écrire "...arr" dans un appel de fonction permet
  // de "spread" le tableau, càd de passer chaque case comme un argument distinct
  return reverseArray(reverseWords(...arr));
}

3-e

Réécrivez les quatre précédentes fonctions de manière récursive.

Correction :

function recursReverseWord(word) {
  // Une bonne technique pour faire une fonction récursive,
  // c'est d'écrire la ou les conditions de sortie.
  // Ici, dès que le mot n'a plus qu'un seul caractère, ou que c'est une chaîne vide,
  // on retourne simplement le mot.
  if (word.length <= 1) {
    return word;
  }
  
  // Pour le reste, on va devoir retourner la concaténation suivante :
  // (le restant du mot) + (premier caractère du mot)
  return recursReverseWord(word.substring(1)) + word[0];
}

// OK, peut-être un peu plus effrayant celui-ci, mais pas forcément très difficile
function recursReverseWords(...words) {
  // Rappel : (...words) signifie que je peux utiliser "words" comme un tableau
  // Quand je n'ai plus qu'une seule case à mon tableau (donc plus qu'un mot)
  // je retourne un nouveau tableau contenant le mot inversé
  if(words.length === 1) {
    return [recursReverseWord(words[0])];
  }
  
  // Pour le reste, je retourne simplement un tableau contenant le premier mot inversé
  // et le reste des mots inversés.
  // "words.slice(1)" signifie que je créé un nouveau tableau depuis la 2ème case
  return [recursReverseWord(words[0]), ...recursReverseWords(...(words.slice(1)))]
}

// Attention c'est technique
function recursReverseArray(arr) {
  // S'il n'y a plus qu'une seule case je la retourne
  if(arr.length === 1) {
    return arr;
  }
  // Pour le reste je retourne une concaténation de tableaux
  // [le reste du tableau] + la première case du tableau
  return [...recursReverseArray(arr.slice(1)), arr[0]];
}

// 200 IQ
function recursReverseAll(arr) {
  return recursReverseArray(recursReverseWords(...words));
}

recursReverseAll(words)