DM 2 (MP2I 2021-2022) — Centrale 2019, compléments¶
Devoir à la maison · MP2I · 2021-2022 · OCaml
Cours : Type option
Remarques globales¶
Certaines questions sont fausses ou mal posées (c'est comme ça parfois le jour du concours :/)
- Question 1 : on renvoie une nouvelle liste vu qu'on ne peut pas les modifier en
OCaml - Question 5 et 6 : très mal posées ainsi, vous les sautez
- Question 11, 12 et 13 : les portes logiques ne sont pas techniquement au programme, ce n'est pas très compliqué, mais si ça ne vous inspire pas, n'hésitez pas à sauter
- Question 16 : l'indication est fausse il faut chercher le plus grand
- Question 18 : C'est le nombre de combinaisons après être arrivé à la combinaison donnée qui importe
- Question 25 : L'ordre précédent est ambigu, je pense que c'est l'ordre lexicographique sur les uplets.
Questions de programmation¶
Vous pouvez accéder à un énoncé ici
Question 1¶
Quelques exemples significatifs, j'écris a1..an pour [a1;...;an] et a -> Some b si suivant
a vaut Some b ou a -> None si suivant a vaut None.
- Comme
1011 -> Some 1100on a01011 -> Some 01100et11011 -> Some 11100. - Comme
1111 -> Noneon a01111 -> Some 10000mais11111 -> None. 0avec 0 chiffres qui a une écriture vide n'a pas de successeur.
On voit donc :
- Qu'on peut raisonner pour
suivant lquandlvautt::qavecsuivant q. - Qu'on va alors faire un cas selon que la valeur de retour soit
Noneou non, puis selon quetsoit1ou0. - Qu'on aura sûrement besoin d'une fonction
let rec zeros (l : int list) : int list= ...telle quezeros qrenvoie une liste avec autant de0que d'éléments deq. Note : on peut aussi le faire directement avecList.init (List.length q) (fun _ -> 0)mais à l'écrit c'est plutôt à vous de le faire.
On pourra donc avoir une structure telle que :
let rec suivant l = match l with
| [] -> None (* cas 3 *)
| t :: q -> match suivant q with
| None -> (* c'est le cas 2 *)
| Some v -> (* c'est le cas 1 *)
Si on voulait le faire en renvoyant un couple int list * bool indiquant le résultat et un
booléen pour dire si on a réussi, on écrirait :
let rec zeros l = match l with
| [] -> []
| _::q -> 0 :: zeros q
let rec suivant l = match l with
| [] -> ([], false)
| t :: q -> let q', b = suivant q in
if b
then (t :: q', true)
else if t = 1
then (l, false)
else (1 :: zeros q, true)
On aurait alors par exemple :
>>> suivant [0;1;1;0;1]
([0;1;1;1;0], true)
>>> suivant [0;1;1;1;1]
([1;0;0;0;0], true)
>>> suivant [1;1;1;1;1]
([1;1;1;1;1], false)
On voit que c'est maladroit de donner une valeur int list quand le booléen est false car
cela signifie qu'on n'a pas réussi à calculer un successeur. C'est pourquoi, je propose
plutôt de renvoyer Some s quand on a réussi à calculer le successeur s (c'est l'équivalent du
couple (s, true)) et None sinon (c'est l'équivalent d'un couple quelconque (_, false) où _
une liste quelconque d'entiers).