Sys.command "ocaml -version";;
The OCaml toplevel, version 4.04.2
- : int = 0
La question de programmation pour ce texte était donnée en page 6, et était assez courte :
"Écrire un programme prenant en entrée deux nombres $a$, $b$, représentés par des écritures en base $B$ avec des chiffres signés entre $-\beta$ et $\beta$, et retournant un résultat ternaire indiquant si $a < b$, si $a = b$ ou si $a > b$. On supposera que $\beta < B < 2 \beta$, et que les écritures de $a$ et $b$ ont même longueur."
Pour représenter ces entiers, on stocke leur base et le tableau de leur coefficients.
type entier = {
base : int;
t : int array
}
;;
type entier = { base : int; t : int array; }
let quatre = {
base = 10;
t = [| 4 |]
}
val quatre : entier = {base = 10; t = [|4|]}
Le "bit" de poids faible est, par convention du texte, à gauche au début du tableau :
let quarantedeux = {
base = 10;
t = [| 2; 4 |]
}
val quarantedeux : entier = {base = 10; t = [|2; 4|]}
Avec l'exemple du texte :
let n2006 = {
base = 10;
t = [| 6; 0; 0; 2 |]
}
val n2006 : entier = {base = 10; t = [|6; 0; 0; 2|]}
let n2006 = {
base = 10;
t = [| 6; 0; 0; 2 |]
}
val n2006 : entier = {base = 10; t = [|6; 0; 0; 2|]}
let n2006_2 = {
base = 10;
t = [| -4; 1; 0; 2 |]
}
val n2006_2 : entier = {base = 10; t = [|-4; 1; 0; 2|]}
let n2006_3 = {
base = 10;
t = [| 6; 0; 0; -8; 1 |]
}
val n2006_3 : entier = {base = 10; t = [|6; 0; 0; -8; 1|]}
let n2006_4 = {
base = 10;
t = [| -4; 1; 0; -8; 1 |]
}
val n2006_4 : entier = {base = 10; t = [|-4; 1; 0; -8; 1|]}
Caml, dans sa toute beauté, ne permet pas de calculer $x^k$ facilement si $x$ est entier...
let rec puissance x k =
match k with
| 0 -> 1
| 1 -> x
| k when k mod 2 = 0 ->
(* x^k = x^(k/2 * 2) = (x^2)^(k/2) *)
puissance (x * x) (k / 2)
| k ->
(* x^k = x^((k-1)/2 * 2 + 1) = x * (x^2)^((k-1)/2) *)
x * (puissance (x * x) ((k - 1) / 2))
;;
val puissance : int -> int -> int = <fun>
puissance 10 0;;
puissance 10 1;;
puissance 10 2;;
puissance 10 3;;
puissance 10 4;;
- : int = 1
- : int = 10
- : int = 100
- : int = 1000
- : int = 10000
On va convertir un entier représenté sous cette forme en un entier machine de Caml :
let valeur {base=b; t=t} =
let v = ref 0 in
let n = Array.length t in
for k = 0 to n - 1 do
v := !v + (t.(k) * (puissance b k))
done;
!v
;;
val valeur : entier -> int = <fun>
valeur quatre;;
- : int = 4
valeur quarantedeux;;
- : int = 42
valeur n2006;;
valeur n2006_2;;
valeur n2006_3;;
valeur n2006_4;;
- : int = 2006
- : int = 2006
- : int = 2006
- : int = 2006
Le texte ne demandait pas une approche particulièrement maligne, donc on va naïvement répondre à la question : on convertit les deux entiers en leur valeur, on les compare et VOILÀ.
let compare_entiers (a : entier) (b : entier) : int =
let va = valeur a in
let vb = valeur b in
compare va vb
;;
val compare_entiers : entier -> entier -> int = <fun>
compare_entiers quatre quarantedeux;;
compare_entiers quarantedeux quatre;;
compare_entiers quatre quatre;;
compare_entiers quarantedeux quarantedeux;;
- : int = -1
- : int = 1
- : int = 0
- : int = 0
compare_entiers n2006 quarantedeux;;
- : int = 1
Voilà pour la question obligatoire de programmation :
Bien-sûr, ce petit notebook ne se prétend pas être une solution optimale, ni exhaustive.