¶
Feuille 2
2022
On veut calculer le poids idéal d'une personne.
Pour cela, on doit avoir trois informations :
T
en cm,A
en années,S
(qui sera donné par une chaîne
"homme"
ou "femme"
).Les formules (très datées et sans aucun fondement scientifique ;-) sont :
(3*T-250)*(A+270)/1200
(T/2 -30 )*(180+A)/200
On va écrire une fonction javascript qui renvoie le poids ideal.
Dans le cas ou les paramètre passés ne sont pas ceux attendus
on renvoi un undefined
ou Nan
ou n'importe
quoi... c'est a l'utilisateur de respecter les paramètres (c'est
dangereux !!!)
On vérifie la conformité des paramètres et on affichera un message d'erreur expliquant l'éventuel problème.
> poidsIdeal(30,180,"homme")
72.5
> poidsIdeal("trente",180,"homme")
'age et la taille doivent être des nombres
lundefined
>
function poidsIdealv1(a,t,s){
switch (s) {
case "homme":return (3*t-250)*(a+270)/1200
case "femme":return (t/2 -30 )*(180+a)/200
}
}
function poidsIdealv2(a,t,s){
if (typeof a !='number' || typeof t != 'number' ){
// on peut verifier plus de chose...
console.log("l'age et la taille doivent être des nombres ")
return;
}switch (s) {
case "homme":return (3*t-250)*(a+270)/1200
case "femme":return (t/2 -30 )*(180+a)/200
default: console.log("pour pouvoir calculer entrez homme ou femme")
} }
Écrire une fonction qui génère une chaîne contenant la suite ordonnée
des lettre minuscules. On demande une solution sans utiliser dans votre
code les lettre b
et z
mais vous pouvez
utiliser charCodeAt()
ou String.fromCharCode
> genMinuscule()
'abcdefghijklmnopqrstuvwxyz'
function genMinuscule(){
let a="a".charCodeAt();
let res=""
for(let i=0;i<26;i++){
+=String.fromCharCode(a+i);
res
}return res;
}
Le codage de César est un manière de crypter un message de manière simple : On choisit un nombre (appelé clé de codage) et on décale toutes les lettres de notre message du nombre choisi.
Par exemple : Si on choisit comme clé le nombre 7. Alors la lettre
A
deviendra H
, le B
deviendra
I
... et le Z
deviendra G
.
> encode("BON",2)
'DQP'
on peut commencer par le cas des chaines en minuscule avec une clef positive
puis on ajoutera les majuscules, les autre caractère ne seront pas modifié
On remarquera facilement que pour décoder, il suffit de faire la même chose mais avec l'opposé de la clé.
=encode("Bonjour ca va !",3)
a'Erqmrxu fd yd !'
> a=encode(a,-3)
'Bonjour ca va !'
>
function encode(chaine,clef){
let min=genMinuscule()
let maj=min.toUpperCase();
let res="";
if( clef<0){clef=26+clef}
for(let i=0;i<chaine.length;i++){
let l=chaine[i];
if (min.indexOf(l) != -1){
=String.fromCharCode("a".charCodeAt()+(chaine.charCodeAt(i)+clef-"a".charCodeAt())%26)
l
}if (maj.indexOf(l) != -1){
=String.fromCharCode("A".charCodeAt()+(chaine.charCodeAt(i)+clef-"A".charCodeAt())%26)
l
}
+=l
res
} return res;
}
Écrire une fonction verifierMotDePass
qui prend en
argument une chaîne de caractère et renvoie true
si elle
contient au moins un chiffre et une majuscule et false
sinon.
On pourra utiliser indexOf
On parcourt la chaîne et on vérifie chaque caractère. Il y a plus simple en utilisant les « expressions régulières ».
function verifierMotDePass(s){
let chiffre=false;
let maj=false;
for(let i=0;i<s.length;i++){
if ("1234567890".indexOf(s[i]) != -1) {chiffre=true;}
if( "ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(s[i]) != -1) {maj=true;}
}return (chiffre && maj);
}
Écrire une fonction qui crée un tableau de n zéro.
function tabZeroN(n){
let res=[]
while(n>0){
.push(0);
res--;
n
}return res;
}
ou sans push
function tabZeroNv2(n){
let res=[]
while(n>0){
-1]=0; // attention on va de n-1 a 0
res[n--;
n
}return res;
}
Même question mais avec n'importe quel valeur passée en argument au lieu de 0
function tabInitN(n,val){
let res=[]
while(n>0){
.push(val);
res--;
n
}return res;
}
Écrire une fonction estCroissante(t)
renvoyant un
booléen indiquant si les éléments de t
sont dans l’ordre
croissant.
function estCroissante(t){
for (let i=0;i<t.length;i++){
if (t[i]>t[i+1]) {return false}
}return true
}
Écrire une fonction estPresent(t,x)
parcourant le
tableau et renvoyant un booléen indiquant si x
est présent
dans `t``
On peut aussi tester l'appartenance à un tableau directement avec
t.indexOf(x)!=-1
ou t.includes(x)
, mais on ne
veux pas les utiliser dans cet exercice.
function estPresent(t,x){
for (let i=0;i<t.length;i++){
if (t[i]===x){
return true
}
}return false;
}
Écrire une fonction qui rend un nouveau tableau où tous les éléments
du tableau en argument sont dupliqués. Par exemple à partir de la
[1,2,3]
on obtient [1,1,2,2,3,3]
.
function duplique(t){
let res=[];
let i=0;
while(i<t.length){
2*i]=t[i];
res[2*i)+1]=t[i]
res[(++; // ne pas l'oublie ou boucle infinie ;-)
i
}return res;
}
Reprendre l’exercice precedent en ajoutant à duplique
un
argument supplémentaire qui donne le nombre de répétition de
l'élément
> dupliqueN(["bonjour","ca va"],4);
['bonjour', 'bonjour',
'bonjour', 'bonjour',
'ca va', 'ca va',
'ca va', 'ca va'
]
function dupliqueN(t,n){
let res=[];
let i=0;
while(i<t.length){
for(let j=0;j<n;j++){
*i)+j]=t[i];
res[(n
}++; // ne pas l'oublie ou boucle infinie ;-)
i
}return res;
}
Écrire une fonction compose
prenant deux tableaux de
même longueur en entrée et renvoyant un tableau dont les éléments sont
des paires (des tableaux à 2 éléments) des éléments des tableaux en
entrée.
> compose([1,2,3],[4,5,6])
1, 4 ], [ 2, 5 ], [ 3, 6 ] ] [ [
function compose(t1,t2){
let res=[]
for(let i=0;i<t1.length;i++){
=[t1[i],t2[i]];
res[i]
}return res
}
Décalage à droite et à gauche. Écrire decalageG
et
decalageD
: deux fonctions effectuant un décalage d’une
position vers la gauche (resp. vers la droite) dans un tableau
(l’élément sortant faisant sa rentrée du coté opposé, votre fonction
modifie le tableau en place).
> decalageD(t)
undefined
> t
5, 1, 2, 3, 4 ]
[ > decalageD(t)
undefined
> t
4, 5, 1, 2, 3 ]
[ > decalageG(t)
undefined
> decalageG(t)
undefined
> t
1, 2, 3, 4, 5 ]
[ > decalageG(t)
undefined
> t
2, 3, 4, 5, 1 ]
[ >
function decalageG(t){
let premier=t[0]
let indiceDernier=t.length-1;
for(let i=1;i<= indiceDernier;i++){ //on décale tous sauf le premier vers la gauche
-1]=t[i]
t[i
}= premier; //on met le premier dans la dernière case
t[indiceDernier]
}
function decalageD (t){
let indiceDernier=t.length-1;
let dernier=t[indiceDernier];
for(let i=indiceDernier-1;i>=0;i--){ //on décale tous sauf le dernier vers la droite
+1]=t[i];
t[i
}0]= dernier; //on met le dernier dans la premiere case
t[ }
Une variante en utilisant shift
(qui retire le premier élément et décale les autres) et push
(qui ajoute un lement à la fin).
function decalageG2(t){
let x=t.shift()
.push(x)
t }
Si on avait demandé de ne pas modifier t
mais de
produire un nouveau tableau on aurait pu écrire:
// ne modifie pas t
function decalageG3(t){
let [premier,...reste]=t; //crée une copie superficielle
.length-1]=premier
reste[treturn reste; // on renvoie une copie (au premier niveau)
}
Functions récursives
Écrire deux fonctions pair
et impair
mutuellement recursive (ie. pair
fait référence à impair
et inversement ) permettant de
tester si un entier donné en argument est paire ou impaire
> pair(8)
true
> pair(9)
false
> impair(8)
false
> impair(9)
true
function pair (x) {
if (x === 0) {return true} else {return impair (x-1)}
}function impair(x){
if (x === 0) {return false} else {return pair (x-1)}
}
Soit un tableau t
de n
entiers, écrire une
fonction récursive simple permettant de déterminer le maximum du tableau
On pourra regarder la Recherche_dichotomique.
:::solution ### Solution
// d et f indice de debut et de fin de recherche dans t
function maximum(t,d,f){
console.log(t,d,f);
if ((f-d)===0){
return t[d]
}// principe de la recherche dichotomique
let m = Math.floor((f-d)/2) //milieu de zone chercher
let max1 = maximum(t,d,d+m) //on cherche sur la premiere moitié
let max2 = maximum(t,m+d+1,f) //on cherche sur seconde moitié
if (max1 > max2){return max1}
return max2
}
function max(t){return maximum(t,0,t.length-1)}
:::
------------------------------------------------
# Exercice
Codage de Vigenère
, pour appliquer un codage de Vigenère il faut décaler les lettres mais pas toutes du même nombre. La clé est cette fois-ci un mot_clé dont chaque lettre nous donne le décalage à effectuer (en prenant A pour un décalage de 0, B pour un décalage de 1 ...).
Tout comme le codage de César
: Imaginons que le mot_clé soit "MATHS" et le mot à coder "PYTHON".
Prenons un exemple pour expliquer la méthode
, je décale du nombre correspondant à M c'est à dire 12 (car on commence à 0 avec A) ce qui me donne B comme codage pour P.
Pour coder P: Je le décale du nombre correspondant au A c'est à dire 0 donc Y est le codage de Y ici.
Passons au Y 'est à dire 19 donc T devient une fois décalé M
Passons au T qui se décale du nombre correspondant à T c.
Ainsi de suite'est à dire que N sera décalé du nombre correspondant à M.
Si notre mot_clé est trop court on recommence au début du mot c
.
Le but de cet exercice est de créer un programme qui reçoit en entrée un mot_clé et un mot à coder et qui affiche le mot codé par cette méthode
: Un mot_clé et un mot à coder écrits en majuscules et sans accent.
Entrée
: Le mot codé par la méthode de Vigenère en majuscule.
Sortie
# Exercices
/split/sort/join)
[](chaine
## Exercice://fr.wikipedia.org/wiki/Anagramme) s' ils ont même longueurs sont composés des même lettres, mais dans des ordres potentiellement différents.
Deux chaîne de caractère sont des [anagrammes](https
Écrire une fonction qui teste si deux chaines:
sont des anagrammes
```javascript
> EstAnagramme("romain","manoir")
true
> EstAnagramme("sortie","toiser")
true
> EstAnagramme("posture","poste")
false
>
function EstAnagramme (str1, str2) {
//si les longueurs
//sont différente ce n'est pas des anagram
if (str1.length !== str2.length) {
return false;
}
//sinon on tri les caractères des deux chaînes.
var s1 = str1.split('').sort().join('');
var s2 = str2.split('').sort().join('');
//on compare les deux chaînes triées.
return (s1 === s2);
}
Les tableaux disposent de fonctionnelles.
– Array.map : (’a -> ’b) -> ’a array -> ’b array
– Array.iter : (’a -> unit) -> ’a array -> unit
– Array.fold_right : (’b -> ’a -> ’a) -> ’b array -> ’a -> ’a
– Array.fold_left : (’a -> ’b -> ’a) -> ’a -> ’b array -> ’a
De plus, certaines fonctionnelles permettent de prendre en compte des fonctions qui agissent différemment selon l’indice d’un élément dans le tableau :
– Array.mapi : (int -> ’a -> ’b) -> ’a array -> ’b array prend en argument une fonction f : [[0; n − 1]] × A −→ B et un tableau [|a0, a1, . . . , an−1|] ∈ An et renvoie le tableau [|f(0, a0), f(1, a1), . . . , f(n − 1, an−1)|].
– La fonction Array.iteri : (int -> ’a -> unit) -> ’a array -> unit prend en argument une fonction f qui renvoie un type unit, c’est-à-dire qui modifie l’environnement, et l’applique sur chaque couple (i, ai) du tableau.
Exercice 1 Implémenter les fonctions map, iteri et fold_left pour les tableaux.
Les matrices peuvent être vues comme des tableaux à deux dimensions. La première idée qui nous vient à l’esprit pour créer une matrice est d’utiliser deux fois la fonction Array.make :
val m : int array array = [|[|1; 1; 1; 1|]; [|1; 1; 1; 1|]; [|1; 1; 1; 1|]|] La modification d’un élément se fait alors de la même façon que pour un tableau, en précisant l’indice de la ligne et de la colonne : # m.(1).(2) <- 5;; - : unit = ()
Cependant, après vérification, le résultat obtenu est étonnant : # m;; - : int array array = [|[|1; 1; 5; 1|]; [|1; 1; 5; 1|]; [|1; 1; 5; 1|]|]
Après réflexion, cela semble normale : lors de la création de la matrice, on a écrit que chaque ligne devait être la même, à savoir une colonne contenant quatre 1.
Les lignes sont alors considérées comme le même objet et la modification de l’une entraînera nécessairement la modification des autres. Nous proposons une première solution pour éviter le problème :
let m = Array.make 3 [||];; for i = 0 to 2 do m.(i) <- Array.make 4 1 done;; m.(1).(2) <- 5; m;; - : int array array = [|[|1; 1; 1; 1|]; [|1; 1; 5; 1|]; [|1; 1; 1; 1|]|] Ou plus simplement : let m = Array.make_matrix 3 4 1;; Exercice 2 Écrire une fonction transpose : ’a array array -> unit qui transpose une matrice carrée. Exercice 3 Écrire une fonction mult : int array array -> int array array -> int array array qui calcule le produit de deux matrices. On supposera que les dimensions permettent de faire le calcul. I.3 Files d’attente
Exercice 13. Des fonctionnelles simples. Écrire une fonction (et prévoir son type) qui à deux fonctions f et g associe : — la fonction composée f ◦ g ; — la fonction min(f, g) — la fonction max(f ◦ g, g ◦ f). Corrigé. On utilise la déclaration de fonctions en leur donnant un nom, plutôt que fun ou function. 1. let compose f g x = f (g x) ;; de type ('a -> 'b) -> ('c -> 'b) -> 'c -> 'b. En effet, le type d’entrée de f est le même que celui de sorti de g. 2. La fonction min de Ocaml est une fonction polymorphe à deux arguments. On propose let mini f g x = min (f x) (g x) ;; de type ('a -> 'b) -> ('a -> 'b) -> 'b. En effet les types d’entrée des deux fonctions f et g sont les mêmes, de même que les types de sortie. 3. let maxi_compose f g x = max (f (g x)) (g (f x)) ;; de type ('a -> 'a) -> ('a -> 'a) -> 'a -> 'a. En effet, pour composer g ◦ f et f ◦ g, les types d’entrée et de sortie de f et g doivent tous être identiques.
On peut calculer le produit \(n_1 \times n_2\) de la façon suivante :
Le procédé s’arrête lorsque \(n_1\) tombe à zéro.
Écrire une fonction multRusse
implémentant cette
idée.
::: Solution
function multRusse(a, b) {
let res = 0;
while (a > 0) {
if (0 === (a % 2)) { //pair
= a / 2;
a = 2 * b;
b
}else { //impair
= res + b;
res --;
a
}
}return res;
}
// ou si on copie le pseudo code de wxikipedia
function multRusse2(a, b) {
let res = 0;
while (a > 0) {
if (0 === (a % 2)) { //pair
}else { //impair
= res + b;
res --;
a
}
= a / 2;
a = 2 * b;
b
}return res;
}
Il s'agit de définir un objet chronometre
avec deux
méthodes. - demarrer
qui démarre le chronomètre -
arreter
qui l’arrête et renvoie le nombre de millisecondes
écoulées depuis le démarrage.
Si le chronomètre n'est pas démarré elle ne fait rien.
On pourra utiliser Date.now()
qui renvoie le nombre de
millisecondes depuis le 1er Janvier 1970.
>chronometre.start()
undefined
> chronometre.end() // presque 2 seconde après
1943
>
let chronometre={
started:false,
current:undefined,
demarrer : function (){ this.started=true; this.current=Date.now(); },
arreter : function (){ if(this.started){this.started=false;return Date.now()-this.current; }}
}
On se donne une collection de valeurs de pièces de monnaies, sous
forme d’un tableau t
(comme
[1, 2, 5, 10, 20, 50, 100]
). On veut calculer le nombre de
façons différentes que l’on a de décomposer une quantité d’argent
s
avec ces pièces.
Écrire une fonction `decomposition(t,s) résolvant ce problème.
Indication : c’est un problème difficile. On construira une matrice (tableau à deux dimensions) de taille (s + 1) × (p + 1), avec p le nombre de pièces.
On calculera le nombre de façon que l’on a de décomposer k avec les i premières pièces du tableau de pièces, et ce pour tout 0 ≤ k ≤ n et 0 ≤ i ≤ p.
```js
function matrice0(n,m){
let mat=[]
for(let i=0;i<n;i++){
mat[i]=[]
for(let j=0;j<m;j++){
mat[i][j]=0;
}
}
return mat
}
function _get_change_making_matrix(pieces, s){
let m=matrice0(s+1,pieces.length +1);
for(let i=1;i< s + 1;i++){
m[0][i] = Infinity // By default there is no way of making change
}
return m
}
function change_making(coins, n){
/* This function assumes that all coins are available infinitely"
n is the number to obtain with the fewest coins.
coins is a list or tuple with the available denominations.
*/
m = _get_change_making_matrix(coins, n)
for(let c=1;c<coins.length;c++){
for (let r=1;r<n+1;r++){
// Just use the coin
if (coins[c] === r){
m[c][r] = 1
}
// coin cannot be included.
// Use the previous solution for making r,
// excluding coin
else if (coins[c] > r){
let zz= m[c - 1][r]
m[c][r] =zz
console.log("QQ",zz);
}
// coin can be used.
// Decide which one of the following solutions is the best:
// 1. Using the previous solution for making r (without using coin).
// 2. Using the previous solution for making r - coin (without
// using coin) plus this 1 extra coin.
else{
let a=m[c - 1][r];
let b=1 + m[c][r - coins[c]];
console.log("AB",a,b)
m[c][r] = Math.min(a,b);
}
}
}
return m;
}
```