Rappels des traits syntaxiques qui doivent vous évoquer quelque-chose.\disablelispcomment (* commentaire *) let VAR = EXPRESSION;; définition globale let FUN VAR+ = EXPRESSION;; définition globale de fonction let DEFINITION codéfinition globale [and DEFINITION]* ;; let rec DEFINITION codéfinition récursive globale [and DEFINITION]* ;;En ce qui concerne les expressions, on trouve:
\disablelispcomment let [rec] DEFINITION [and DEFINITION]* définition locale in EXPRESSION if EXPRESSION_BOOLEENNE then EXPRESSION alternative else EXPRESSION ( EXPRESSION [EXPRESSION]* ) appel de fonction EXPRESSION OPERATEUR-INFIXE EXPRESSION opération binaire function VAR -> EXPRESSION création de fonction unaire match EXPRESSION with filtrage explicite PATTERN -> EXPRESSION [ | PATTERN -> EXPRESSION ]* end for VAR = EXPRESSION to EXPRESSION do boucle EXPRESSION [ ; EXPRESSION]* done
Écrire une fonction compter qui prend un entier et une liste d'entier et compte les occurrences de ce premier dans cette dernière.
Écrire une fonction au_moins_deux retournant les entiers apparaissant au moins deux fois dans une liste d'entiers. Aucun ordre n'est exigé dans la réponse, les répétitions y sont également permises.
Écrire la fonction exactement_deux qui extrait d'une liste de nombres ceux qui y apparaissent exactement deux fois. La solution ne doit pas comporter de répétition.
Écrire la fonction xpl dont voici un exemple:
xpl [1; 2; 3; 4];; - : int list list = [[1]; [1; 2]; [1; 2; 3]; [1; 2; 3; 4]]
Soit le générateur linéaire suivant:
let generateur_lineaire a b c = function n -> (a * n + b) mod c;; generateur_lineaire : int -> int -> int -> int -> int = <fun>
On peut alors construire une sorte de dé à jouer, ainsi:
let de = generateur_lineaire 1 2 6;; de : int -> int = <fun>
Mais il n'est pas très aléatoire comme le montre:
for i = 1 to 20 do print_int (de i); print_string " " done;; 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 - : unit = ()
Écrire le prédicat boucle qui teste si un tel dé boucle ou plus généralement si les termes de la suite f(i) bouclent? On utilisera la méthode de Floyd qui consiste à comparer les n ème et 2n ème lancers de dé ou termes de la suite. En effet la suite boucle ssi il existe n tel que f(n)=f(2n).
Modifier la fonction précédente de telle sorte qu'elle retourne un élément du cycle trouvé. On utilisera un générateur du second ordre:
let generateur_second_ordre a b c d = function n -> (a * n * n + b * n + c) mod d;; generateur_second_ordre : int -> int -> int -> int -> int -> int = <fun> let f = generateur_second_ordre 23 12 31 67;; f : int -> int = <fun>
Modifier encore une fois la précédente fonction de manière qu'elle retourne la liste des entiers composant le premier cycle trouvé.
Toutes ces fonctions ont une structure quasiment identique: elles sont paramétrables par la condition de fin et le traitement final. Abstraire les fonctions précédentes en la fonction jusque_a de signature:
jusque_a predicat traitement f x0Puis définir, à l'aide de jusque_a, les fonctions boucle et boucle_et_trouver_element_du_cycle.
Utiliser la méthode de Brent pour savoir si une fonction boucle. Elle permet de rechercher un élément de cycle plus petit que la méthode de Floyd. Elle revient à comparer f(0) avec les deux suivants f(1) et f(2), puis f(2) avec les quatre suivants f(3), f(4), f(5), f(6), puis f(6) avec les huit suivants f(7) ...
Écrire une fonction recherchant aléatoirement des diviseurs d'un nombre. Comme générateur aléatoire, on pourra prendre:
let alea n = generateur_second_ordre 1 0 1 n;; alea : int -> int -> int = <fun> for i = 1 to 20 do print_int (alea 100 i); print_string " " done;; 2 5 10 17 26 37 50 65 82 1 22 45 70 97 26 57 90 25 62 1 - : unit = ()
Modifier la fonction précédente pour utiliser la méthode de Floyd-Pollard.