Télécharger la présentation
La présentation est en train de télécharger. S'il vous plaît, attendez
Publié parGabin Lefebvre Modifié depuis plus de 8 années
1
IFT359 – Programmation fonctionnelle Thème #6 Appel terminaux 1
2
Récursivité directe/indirecte (define f (λ (x) (if (> x 10) #t (g x)))) (define g (λ (n) (if (> n 5) (f (+ n 1)) (g (+ n 1))))) Récursivité directe Récursivité indirecte (define fact (λ (n) (if (= n 0) 1 (* n (fact (- n 1)))))) 2
3
Appel terminal (tail call) Récursivité terminale (tail recursive) (fact 5) >(fact 5) > (fact 4) > >(fact 3) > > (fact 2) > > >(fact 1) > > > (fact 0) < < < 1 < < 2 < <6 < 24 <120 ->120 (define fact (λ (n) (if (= n 0) 1 (* n (fact (- n 1)))))) Observez la trace de (fact 5) 3
4
Appel terminal (tail call) Récursivité terminale (tail recursive) (define drop (λ (n lst) (if (= n 0) lst (drop (sub1 n) (cdr lst))))) (drop 3 '(a b c d e)) >(drop 3 (a b c d e)) >(drop 2 (b c d e)) >(drop 1 (c d e)) >(drop 0 (d e)) <(d e) ->(d e) 4
5
Appel terminal (tail call) Récursivité terminale (tail recursive) (define fact (λ (n) (if (= n 0) 1 (* n (fact (- n 1)))))) (define drop (λ (n lst) (if (= n 0) lst (drop (sub1 n) (cdr lst))))) Dernier appel d’une procédure Il peut y en avoir plusieurs (e.g. cond ) Si c’est un appel récursif direct, on parle de récursivité terminale Peut être optimisé par le compilateur En Scheme (DrRacket), garanti par la spécification Une procédure récursive terminale est grosso modo équivalente à une boucle en C Exécution d’une λ = « GOTO avec paramètres » 5
6
Récursivité terminale : Exemple (define fact-iter (λ (n) (let iter ([res 1] [k n]) (if (> k 0) (iter (* k res) (sub1 k)) res)))) (define reverse-iter (λ (lst) (let iter ([reste lst] [res '()]) (if (null? reste res (iter (cdr reste) (cons (car reste) res)))))) 6
7
Récursivité terminale : Exemple (define length-iter (λ (lst) (letrec [iter (λ (reste res) (cond [(null? reste) res] [else (iter (cdr reste) (add1 res))]))]) (iter lst 0)))) 7
8
Application de la récursivité : algorithme de type « diviser pour reigner » (define quicksort (λ (lst) (if (or (null? lst) (null? (cdr lst))) lst (let* ([pivot (car lst)] [reste (cdr lst)] [before (filter (curryr <= pivot) reste)] [after (filter (curryr > pivot) reste)]) (append (quicksort before) (cons pivot (quicksort after))))))) Que pensez-vous du Quicksort ? 8
9
Application de la récursivité : Fouille (define binsearch (λ (vect value) (let search ([min 0] [max (vector-length vect)]) (if (or (> 0 min) ( max (vector-length vect)) #f (let ([mid (+ min (quotient (- max min) 2))]) (cond [(> (vector-ref vect mid) value) (search min (sub1 mid))] [(< (vector-ref vect mid) value) (search (add1 mid) max)] [else mid])))))) Que pensez-vous de binsearch ? 9
10
Application de la récursivité : Automate Scanner pour c[a|d] + r Exercice : Créer une procédure cadr-scanner qui prend en entrée une liste et qui retourne #t si cette liste peut être produire par cet automate sinon #f. 10
11
Application de la récursivité : Automate (define cadr-scanner (λ (i) (letrec ([C (λ (i) (cond [(null? i) #f] [(eq? (car i) 'c) (AD (cdr i))] [else #f]))] [AD (λ (i) (cond [(null? i) #f] [(or (eq? (car i) 'a) (eq? (car i) 'd)) (AD (cdr i))] [(eq? (car i) 'r) (R (cdr i))] [else #f]))] [R (λ (i) (cond [(null? i) #t] [else #f]))]) (C i)))) 11
12
Application de la récursivité : Arbre et graphe (define flatten-iter (λ (tree) (let loop ([tree tree] [stack '()] [l '()]) (cond [(and (null? tree) (null? stack)) (reverse l)] [(null? tree) (loop (car stack) (cdr stack) l)] [(and (atom? tree) (null? stack)) (reverse (cons tree l))] [(atom? tree) (loop (car stack) (cdr stack)(cons tree l))] [else (loop (car tree) (append (cdr tree) stack) l)])))) Est-ce plus efficace que la récursivité naturelle ? 12
13
Application de la récursivité : Fractale (define sierpinski (λ (a b c) (unless (too-small? a b c) (let [a-b (mid-point a b)] [b-c (mid-point b c)] [c-a (mid-point a c)]) (draw-triangle a b c) (sierpinski a a-b c-a) (sierpinski b a-b b-c) (sierpinski c c-a b-c))))) 13
14
La fonction d’Ackerman (define A (λ (m n) (cond [(= m 0) (+ n 1)] [(and (> m 0) (= n 0)) (A (- m 1) 1)] [(and (> m 0) (> n 0)) (A (- m 1) (A m (- n 1)))]))) Elle explose très rapidement, mais elle est totale (en théorie) A(4, 2) = 2 65536 14
15
Mémoization Quand une (f n) est définie par rapport aux valeurs de (f (- n1)), …, (f (- n k)) –Fibonnaci (version co-récursive) –Ackerman (tester avec m=3, n=12) On sauvegarde les anciennes valeurs –On peut utiliser les hashtable Plus efficace qu’une liste –On forme la clé avec une liste contenant tous les arguments 15
16
Mémoization (define memoize (λ (f) (let ([table (make-hash)]) (λ args (cond [(hash-has-key? table args) (hash-ref table args)] [else (let ([result (apply f args)]) (hash-set! table args result) result)]))))) 16
17
memoizedAckerman (define mA (memoize (λ (m n) (cond [(= m 0) (+ n 1)] [(and (> m 0) (= n 0)) (mA (- m 1) 1)] [(and (> m 0) (> n 0)) (mA (- m 1) (mA m (- n 1)))])))) On peut encore faire mieux avec les macros (define A (λ (m n) (cond [(= m 0) (+ n 1)] [(and (> m 0) (= n 0)) (A (- m 1) 1)] [(and (> m 0) (> n 0)) (A (- m 1) (A m (- n 1)))]))) 17
18
foldl-iter (define foldl-iter (λ (proc init lst) (let iter ([reste lst] [res init]) (if (null? reste) res (iter (cdr reste) (proc (car reste) res)))))) brillant ? 18
19
foldl-iter (define foldl (λ (fn ini liste) (if (null? liste) ini (foldl fn (fn (car liste) ini) (cdr liste))))) brillant ? bof! c’était un bon exercice sur les named let Essayez de faire foldr-iter sans faire de reverse (directement ou indirectement) 19
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.